Server-side safety
Handle file uploads safely
Limit upload size, verify content, generate server-side filenames, isolate storage, and avoid serving untrusted files as executable content.
8 minute lesson
A file upload crosses several trust boundaries at once. The request contains user-controlled bytes, a user-controlled filename, and a user-controlled declared media type.
No single check makes that safe. Use layers.
Limit the request early
Set a total request limit before buffering the complete body. Set a per-file limit too. A 20 MB compressed archive can expand far beyond 20 MB, so avoid accepting archive formats unless the product truly needs them and you can inspect them safely.
Allow only required formats
Start from a small allowlist. If the feature needs profile photos, accepting JPEG and PNG is easier to defend than accepting every file type.
Do not trust file.type, the multipart Content-Type, or the filename extension. They are hints supplied by the client. Inspect the file signature and parse the content with a suitable maintained library. For images, decoding and re-encoding can produce a clean output for the formats you support.
Control storage
Generate a random storage name. Keep the original name only as untrusted metadata when the interface needs to display it.
Store uploads outside executable application directories. Ideally, serve public files from an isolated origin or through a download handler that maps a record ID to the stored object.
Set a correct response Content-Type. For content that should not render in the browser, use a download response. Active formats such as HTML and SVG need extra care because they can execute or reference other content when served incorrectly.
Check permission and lifecycle
Verify that the current user may upload and later access the file. Scan files when the risk warrants it. Define retention, deletion, and storage quotas so abandoned uploads do not grow forever.
Process uploads in a restricted environment. A parser bug should not grant access to application secrets or the main filesystem.
Test an oversized file, a renamed executable, a valid image with a strange filename, two files with the same original name, and an unauthorized download. The visible file picker cannot cover these server-side cases.
Lesson completed