Security

File Uploads & Handling

Intermediate

Letting users upload files — KYC documents, proofs of address, images — is necessary and dangerous. An upload is untrusted input. It can carry malware, be huge, pretend to be a type it is not, or try to escape into your filesystem. Validate strictly, store safely, and serve carefully.

Uploads bring several risks together: malicious content (malware, embedded scripts), resource abuse (huge files filling disk or memory), type tricks (an executable renamed to .pdf, or an image that is really HTML the browser runs), and path traversal (a filename like ../../etc/passwd). For us, uploads are also usually special-category KYC data, so they need strong protection at rest.

Treat every upload as hostile until proven otherwise. Check it at the trust boundary (see Trust Boundaries), store it apart from where it is served, and never trust the client-supplied name or type.

Validate the upload

Store and serve safely

Trust name and type, serve inline var path = Path.Combine("uploads", file.FileName); // ../../ escapes
File.WriteAllBytes(path, bytes);
// later served inline from /uploads with the original type

Path traversal through the filename, no size or type validation, and serving inline. An uploaded .html or .svg file then runs as script for whoever views it. Three classic upload vulnerabilities at once.

Own name, validated, isolated if (bytes.Length > MaxSize) return TooLarge();
if (!IsAllowedType(Sniff(bytes))) return Unsupported();
var blobName = Guid.CreateVersion7().ToString(); // our name, not theirs
await blob.UploadAsync(container, blobName, bytes); // isolated storage
// served via an authorised endpoint with Content-Disposition: attachment

Size and real type are checked, the storage name is ours (no traversal), files live in separate storage, and they are served as downloads, not as content that can run.

Self-review checklist

Why it matters: Upload handling is a common source of serious vulnerabilities — malware delivery, stored XSS, path traversal, denial of service. Our uploads are usually the special-category identity data we are most obliged to protect. Strict validation, separate storage, and careful serving turn a dangerous feature into a safe one.