Files, and why they should not touch your server
Presigned URLs, size limits before the bytes arrive, content-type you do not trust, and processing that happens afterwards.
Routing a hundred megabyte upload through your application server means buffering or streaming it through a process that is also serving requests, on a platform that probably has a body size limit and definitely has a timeout. Issue a presigned URL instead: your server authorises the upload and returns a short-lived URL, the browser sends the bytes directly to object storage, and then tells your server the key. Your server handles two small JSON requests and no file at all.
Constrain the presigned URL when you issue it, because that is your only chance. A short expiry, a maximum size the storage service enforces, a key prefix derived from the authenticated user so nobody can overwrite anyone else's object, and a bound content type. Anything you do not constrain there is unconstrained.
Do not trust the declared type or the extension. A file called invoice.pdf can be anything, including something a downstream image processor will misinterpret. Sniff the actual bytes after upload, re-encode images rather than serving what was sent, and serve user content from a separate origin with Content-Disposition set, so a crafted upload cannot execute as script against your domain.
You should now be able to
- Design an upload that goes straight to object storage
- Enforce size and type limits safely
- Explain why the client-declared content type is not evidence
Loading…