File & Blob Storage
Documents, images, and other binary files belong in dedicated object storage (for example, Azure Blob Storage), not in the database or on a web server's disk. Stored well, files are cheap, scalable, and secure. Stored carelessly, they become public links, lost data, or special-category leaks. Keep them private, access-controlled, and served through short-lived signed URLs.
Object storage is the right home for files, but its defaults and access model catch people out. The common mistakes are: a publicly readable container, guessable URLs, no encryption on sensitive data, no tenant isolation, and serving files straight from a public path. Our files are usually KYC and identity documents, so they are special-category data and need the strongest handling (see Data Classification, Data Protection & Privacy).
Pair this with File Uploads & Handling, which covers validating what comes in. This topic is about storing and serving the file safely once it is in.
Store privately and safely
- AlwaysKeep storage containers private by default, never publicly readable. Grant access explicitly, per request (see Secure Defaults).
- DoEncrypt files at rest and isolate them by tenant (a separate container, path, or key per tenant where it limits the damage from a breach) (see Multi-Tenancy).
- DoUse opaque, unguessable storage names (for example, UUIDv7). Never build the stored path from user input or sequential ids.
- DoApply retention and lifecycle rules to stored files in line with the data's classification, and soft-delete or retain regulated documents per policy (see Data Retention & Erasure).
- NeverMake a container or file holding personal or KYC data publicly accessible, or reachable by a guessable URL.
Serve through controlled access
- DoServe files through an authorised endpoint that checks the caller may access this file, or a short-lived, scoped signed URL (SAS). Do not use a permanent public link.
- DoAccess storage from the app with a managed identity and least-privilege credentials, not a long-lived account key (see Managed Identity & Least-Privilege).
- DoRecord access to sensitive documents in the audit trail: who viewed or downloaded what, and when (see Audit Trails).
- ConsiderVersioning or immutability for documents that must not change, and integrity checks (hashes) for important files.
- AvoidStoring files in the database (it bloats and slows the database) or on an instance's local disk (lost on restart or scale, not shared, not backed up).
// container set to public; file named by customer id
https://acct.blob.core.windows.net/docs/customer-1024-passport.jpg
Anyone can guess the URL and download any customer's passport. This is a severe special-category breach, served straight from public storage.
// container private; opaque name; access checked, then a SAS is issued
var sas = blob.GenerateSas(name, perms: Read, expires: now+5min);
// the app authenticates to storage via a managed identity
Files are private, names are not guessable, and access is a time-limited URL issued only after an authorisation check. The download can also be audited.
Self-review checklist
- AskIs the container private, and is access always authorised per request?
- AskAre storage names opaque, or could a URL be guessed to reach another customer's file?
- AskIs this data, which is likely KYC, encrypted and tenant-isolated at rest?
- AskAm I using a managed identity rather than a long-lived storage key?