All field notes

Building a fail-closed malware gate for automated downloads

How to keep untrusted files away from media services until scanning, verification, and release all succeed.

Automation is useful precisely because it removes human waiting. That same quality makes it dangerous when untrusted files move through a pipeline faster than anyone can inspect them. This guide develops a safer pattern: isolate first, scan second, verify the result, and release only after every condition is satisfied.

Fail-closed malware intake flowDownloader feeds isolated staging, which feeds the scanner, then verification, then release. On scan failure, the flow branches from the scanner to quarantine instead of release. An animated sequence draws this architecture flow and a documented failure path when the diagram enters view; the finished diagram is fully visible either way.on failureDownloaderTrust boundary: staging is enforced at the filesystem level, not just by application ordering.IsolatedstagingScannerVerificationReleaseEvery ambiguous outcome leaves the file isolated rather than released — this is the fail-closed state.Quarantine
Downloader → isolated staging → scanner → verification → release. On scan failure, the flow branches from the scanner to quarantine instead of release.
01

The trust boundary

A downloader should be treated as an untrusted ingestion service. Its output is not part of your library merely because a transfer completed. Place completed files in a staging path that downstream applications cannot read.

This is stronger than relying on application order. A filesystem boundary turns an operational expectation into an enforceable control: if the gate fails, content remains invisible.

02

Design the state machine

Use explicit states: downloading, complete, scanning, clean, released, and quarantined. Never infer completion from a filename alone, and never let a scanner timeout become an implicit pass.

DOWNLOADING → COMPLETE → SCANNING → CLEAN → VERIFIED → RELEASED
                              └→ INFECTED / ERROR → QUARANTINED
03

Verify the release

A successful move command is not enough. Confirm the destination exists, compare the expected size, and ensure the staging source is no longer exposed. Apply a bounded retry policy and fail closed when verification cannot complete.

Logs should record identifiers and outcomes without exposing credentials or full private paths. Alert on stuck scans, repeated replacement attempts, and any transition that bypasses verification.

04

Test the failure paths

The useful tests are uncomfortable ones: an incomplete transfer, a scanner outage, a malicious test file, two workers racing for the same item, and a release operation that reports success without moving data.

Evidence

A control is only proven when its failure mode is safe. In this design, every ambiguous outcome leaves the file isolated.