Hand Off File Upload Scanning Without Skipping Quarantine

Define the scan states, the quarantine owner, and the evidence that a rejected file never reaches a download link.

Hand Off File Upload Scanning Without Skipping Quarantine
WORK_LANE / FIELD GUIDE / DELIVERYREVIEW QUEUEACCEPTANCEPASSowner review requiredEVIDENCE TRAILTICKET → BRANCH → REVIEW → CLIENT RELEASE
On this page
  1. Quick read
  2. Readiness check
  3. Model the upload as states with owners
  4. Write the handoff ticket around one upload path
  5. Build fixtures for clean, rejected, and undecided files
  6. Keep quarantine and delivery storage separate
  7. Prove the denial, not only the success
  8. Test outage, retry, and duplicate upload
  9. Measure coverage and unserved rejections
  10. Close with a state table and a denial record
  11. Role brief
  12. Frequently asked questions
  13. Sources

Is the handoff ready?

Use these checks before access expands or the first ticket begins.

States

Ready: Uploaded, scanning, clean, rejected, deleted with owners

Needs work: A single scanned flag

Storage

Ready: Private bucket, short lived signed links

Needs work: Public bucket with an unguessable name

Failure

Ready: Timeout and outage route to quarantine

Needs work: Failure treated as clean

Release

Ready: Owner reviews quarantined files

Needs work: Automatic release after a retry

Model the upload as states with owners

An upload passes through received, stored, scanning, clean, rejected, and deleted. Each transition needs a trigger, a timestamp, and an owner. A single scanned boolean collapses those states and hides the most dangerous one, which is stored but not yet decided.

Write the rule for each state. A file in scanning cannot be served. A file that fails the scan cannot be served and cannot be re-scanned into clean without an owner action. A file that times out is not clean by default.

Name who can move a file from rejected to released, and who can delete a quarantined object. Those are company decisions with customer and legal consequences, not maintenance tasks.

Give every state a maximum age. A file that sits in scanning for a week is an operational failure even if it is never served, and the age threshold is what turns the state table into a queue someone can work.

Write the handoff ticket around one upload path

The ticket names the upload endpoint, the storage bucket, the scanner, the callback or queue, the download route, and the retention rule. It also names the reviewer and the owner of the bucket policy.

Keep the first ticket to one file type and one path. A Philippines-based programmer can then build fixtures, run the scan, and show the download denial for a rejected object without touching every media route in the product.

Ask for a sequence diagram in the pull request only if the existing docs are wrong. A short written state table is usually more useful than a diagram nobody updates.

Build fixtures for clean, rejected, and undecided files

The clean fixture is easy. The rejected fixture needs a file the scanner will actually flag in the sandbox, using the vendor test pattern or a documented test object. The undecided fixture needs the scanner to hang or fail.

Record the fixture hash, the size, the declared content type, and the observed scan result. If the scanner uses a vendor signature set, note the version and whether it can be refreshed in the sandbox.

Test the mismatch case as well: a file whose declared type differs from its detected type. The rule should be explicit about which value decides the scan and which value decides how the file is served.

  • Clean file: served through a short lived link after the scan completes.
  • Rejected file: no link, no public URL, object retained in quarantine.
  • Timeout: file stays undecided and unserved until an owner acts.
  • Type mismatch: policy decides, and the decision is logged.

Keep quarantine and delivery storage separate

Quarantine should be a different prefix or bucket with a different policy from the delivery store. A rejected object that shares a public prefix is exposed even if the application refuses to link it.

Check the signed link lifetime and whether the link survives a state change. A link issued while the file was clean can outlive a later rejection, so revocation needs a bounded lifetime and a cache rule.

The programmer needs sandbox bucket rights and read access to scanner logs. They do not need the ability to change a production bucket policy, disable the scanner, or release quarantined content.

Prove the denial, not only the success

Evidence includes the object key, the state transitions with timestamps, the scanner result, the download attempt and its status, and the bucket policy in force. A clean upload screenshot shows one half of the control.

Ask for a direct request to the storage URL as well as the application route. The direct request is where a public bucket or an overbroad signed link shows up.

Record the retention and deletion evidence. A rejected object that lingers forever is a data handling problem even when it is never served.

Test outage, retry, and duplicate upload

Scanner outages are normal. The rule must route the file to quarantine or hold it in undecided, never to clean. Test by pointing the sandbox at an unreachable scanner endpoint.

Retries can create two scan records for one object. Define which record wins and how the state machine avoids oscillation. Test a duplicate upload of the same content under a new key and decide whether it inherits the prior verdict.

Large files and slow streams deserve a case. A scan that starts before the upload finishes can produce a false clean result on a partial object.

  • Scanner unreachable for the duration of the test.
  • Scanner returns an error after accepting the object.
  • Duplicate scan callback for one object.
  • Upload interrupted after the object is written.

Measure coverage and unserved rejections

Measure files scanned divided by files accepted, rejected files without a delivery link divided by all rejected files, and time from upload to decision at the ninety fifth percentile. Report the observation window and the file count.

Track undecided files older than one business day. That count is the operational backlog of the control and deserves an owner, not a dashboard footnote.

Review weekly while the feature is new and monthly afterwards. Any change to the scanner, bucket policy, or download route triggers a new rehearsal.

Close with a state table and a denial record

The handoff contains the state table, the fixture hashes, the scanner version, the bucket policies, the denial evidence, the retention rule, and the unresolved cases. Add the owner for quarantine release and the next review date.

Accept the work when a reviewer can upload each fixture and see the correct state, and when a direct storage request for a rejected object fails without a manual step.

Include the scanner callback endpoint and its authentication rule. A callback that accepts an unsigned result can move a file to clean without a scan.

Put the operating agreement in writing.

Path

One upload endpoint, one bucket, one scanner, one download route.

States

Received, stored, scanning, clean, rejected, deleted with owners.

Evidence

State timestamps, scan result, denial status, bucket policy.

Authority

Company owner controls policy, quarantine release, and deletion.

Frequently asked questions

Is a failed scan the same as a rejection?

No. A failure is undecided and stays unserved. A rejection is a decision that a named owner can review.

Can the programmer test with a real infected sample?

Use the scanner vendor test object or a synthetic pattern approved by the company. Do not move live malware into a shared environment.

Who can release a quarantined file?

A named company owner after a documented review. Automatic release defeats the control.

Sources

  1. OWASP Application Security Verification Standard

    File upload and access control verification requirements.

  2. CISA Secure by Design

    Design guidance for secure defaults and reduced attack surface.

  3. NIST Secure Software Development Framework

    Protection practices for artifacts and deployment environments.

  4. NIST Cybersecurity Framework 2.0

    Detection and response framing for scanner outages.

Build a programming lane your technical owner can review.

Bring the stack, backlog, acceptance checks, and release boundaries. We will help scope the role around the work.

Discuss your programming needs