Files and uploads Required
Scan files for malware before anyone opens them
Scan every file that other people or systems will open, and serve it only after the scan says clean.
How to do it
Upload into a quarantine prefix or bucket that nothing serves. Scan on the storage event with a scanner such as ClamAV. Storage services offer it too, such as GuardDuty Malware Protection for S3 or Microsoft Defender for Storage. ClamAV skips files over its size limits and reports them clean. Raise MaxFileSize and MaxScanSize above your upload limit, and set AlertExceedsMax yes. Treat a scanner error as not clean. Move clean files to the served location and record clean with the scanner's version. Move infected files to an infected/ prefix that nothing serves, keep them 30 days for review, then delete them. Downloads check the status on every request, so a file that fails a later rescan stops at once. Update the scanner's signatures at least daily.
Example
import { execFile } from 'node:child_process';
const SCAN_RESULT = { 0: 'clean', 1: 'infected' };
export function scanFile(path) {
return new Promise(resolve => {
execFile('clamdscan', ['--no-summary', '--fdpass', path], error => {
resolve(SCAN_RESULT[error?.code ?? 0] ?? 'scan-failed');
});
});
}
export function assertDownloadable(file) {
if (file.scanStatus !== 'clean') {
throw new ProblemError(403, 'https://api.example.com/problems/file-not-scanned', 'This file has not passed the malware scan.');
}
}
import subprocess
SCAN_RESULT = {0: "clean", 1: "infected"}
def scan_file(path: str) -> str:
finished = subprocess.run(["clamdscan", "--no-summary", "--fdpass", path], capture_output=True)
return SCAN_RESULT.get(finished.returncode, "scan-failed")
How to check
Upload the EICAR test file. It stays in quarantine, its status reads infected, and a download request answers 403 or 404.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers api design playbook: https://agentwranglers.se/playbook/api-design/files-and-uploads/scan-uploads.