Files and uploads Required
Confirm every upload on the server
Keep a new file pending until the server has checked its size, type and checksum from the stored bytes. Never trust what the client reports.
How to do it
When the client says the upload is done, or storage sends its event, read the stored object. Compare its size with your limit. Find its type from the first bytes, and checksum it with SHA-256. Store all three in your files table. Only then mark it ready for the next step. The attacks this blocks, and how to test for them, are in check every uploaded file. Delete pending files that were never confirmed within 24 hours.
Example
import { fileTypeFromBuffer } from 'file-type';
const ALLOWED_TYPES = new Set(['image/jpeg', 'image/png', 'application/pdf']);
export async function confirmUpload(firstBytes, storedSize, maxBytes) {
const detected = await fileTypeFromBuffer(firstBytes);
if (storedSize > maxBytes) return { status: 'rejected', reason: 'too-large' };
if (!detected || !ALLOWED_TYPES.has(detected.mime)) return { status: 'rejected', reason: 'type-not-allowed' };
return { status: 'awaiting-scan', mime: detected.mime };
}
import magic
ALLOWED_TYPES = {"image/jpeg", "image/png", "application/pdf"}
def confirm_upload(first_bytes: bytes, stored_size: int, max_bytes: int) -> dict:
detected = magic.from_buffer(first_bytes, mime=True)
if stored_size > max_bytes:
return {"status": "rejected", "reason": "too-large"}
if detected not in ALLOWED_TYPES:
return {"status": "rejected", "reason": "type-not-allowed"}
return {"status": "awaiting-scan", "mime": detected}
How to check
Upload a text file named photo.jpg with a content type of image/jpeg. The file never leaves pending, and the API answers with a problem response naming the type.
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/confirm-uploads.