Secure file uploads in SaaS: validation, storage and download checklist
Protect a SaaS file-upload flow with allowlisted formats, size limits, quarantine scanning, private storage and tenant-checked downloads.
In this guide
What makes a SaaS file-upload feature risky?
An uploaded file is untrusted input that may target storage, parsers, other users or shared infrastructure. A secure design checks who may upload, which formats the feature needs, how large files can be and how they are stored and served. OWASP recommends layered controls because filename, extension, MIME type or antivirus scanning alone cannot prove that a file is safe.
Allow only the formats the product needs
Define a short allowlist for each upload feature and reject everything else. Decode and normalise the filename before checking its extension, and check file signatures alongside content type; the browser-supplied MIME header is not trustworthy. Do not accept executable or active formats merely because the product may support them someday.
Set size, count and processing limits
Limit bytes per file, files per request, archive expansion, image dimensions, processing time and concurrent jobs. Enforce limits at the edge and in the application so a reverse proxy or worker cannot be exhausted by a large or highly compressed file. Return a clear error and provide a safe retry route.
Replace user filenames with generated storage identifiers
Treat names and paths from the request as display metadata only. Generate a random storage key, prevent path traversal and overwrite, and store the original display name separately after length and character checks. Do not use a user-controlled name as a filesystem path, object key or executable response header.
| Upload use case and allowed types | Size / count / processing cap | Storage and scan state | Tenant download check | Owner / test date |
|---|---|---|---|---|
| Profile image | ||||
| Customer document | ||||
| Bulk archive or export |
How should a SaaS product store and scan uploaded files?
Keep new files private and quarantined until checks finish
Store uploads outside the public web root or in a private object bucket. Mark a file pending while malware scanning, content disarm or format-specific validation runs. Make it available only after the expected checks succeed; define how a scan failure or unsupported encrypted document is handled.
Scan with layered controls appropriate to the format
Use malware detection or sandboxing where suitable and consider content disarm and reconstruction for document types that support it. Parse images, PDFs and archives with maintained libraries, isolated workers and resource limits. A clean scan is one signal, not proof that a file is harmless or appropriate to share.
Separate the customer's filename from the served content
When returning a file, set a deliberate content type and safe Content-Disposition behavior. Avoid rendering untrusted HTML or SVG inline on the main application origin. Consider a separate content origin and short-lived signed download URL when public access is not required.
How do you prevent cross-tenant file access?
Authorize every upload and download against the tenant
Resolve the authenticated user's tenant from trusted server-side state and verify ownership or an explicit share grant before reading, replacing, listing or deleting each object. Do not treat an unguessable object key or hidden download link as authorization. Test direct-object access across two tenants.
Apply the same checks to thumbnails, previews and background jobs
Derived files can expose the original even when the primary object is private. Carry tenant and object ownership through image resizing, OCR, preview generation, exports, backups and deletion tasks. Ensure temporary URLs expire and cannot be reused to fetch a different tenant's object.
Test malicious and unusual inputs before release
Cover double extensions, null bytes, spoofed content types, path traversal, duplicate filenames, huge images, compressed archives, corrupted documents and requests without permission. Check the stored object, browser response headers, scanning status and logs. Use safe test files in an isolated environment.
SaaS file-upload questions
Is checking the file extension enough?
No. An extension can be misleading or crafted to bypass a simple check. Use a narrow allowlist, decode and normalise names, inspect expected signatures, cap resource use, store privately and scan or process files with appropriate isolation.
Can I trust the browser's Content-Type header?
No. It is supplied by the client and can be spoofed. Compare it with the expected extension and file signature, and reject a mismatch or unsupported format according to a documented policy.
Should uploaded files be stored in the same database?
That depends on product needs and architecture. Object storage is common for larger files, but it still needs private access, generated keys, encryption, lifecycle rules and tenant-aware authorization. A separate storage service alone does not prevent exposure.
Is antivirus scanning enough to make downloads safe?
No. Scanning reduces some risks but can miss new or file-specific threats. Combine it with format limits, private storage, safe parsing, tenant checks, response headers and a process for quarantine and suspicious files.
Related practical guides
Related issue guides
Sources and publication record
Draft prepared 27 September 2026; engineering, security and editorial review pending · Sources checked .
- OWASP Cheat Sheet: File UploadOWASP Foundation
- AWS SaaS Lens: Preventing cross-tenant accessAmazon Web Services
- OWASP Cheat Sheet: LoggingOWASP Foundation