Security & Privacy

Secure File Uploads: How Web Apps Get It Wrong and How to Fix It

File uploads are one of the riskiest features in any web app. Learn the common mistakes and a layered approach to validation, storage, access control and scanning.

Illustration of documents and images passing through a scanning gate into a locked storage vault

Upload forms look harmless: a CV on a careers page, product images in an admin panel, a lab report in a patient portal, a 3D model on a marketplace. Yet file uploads are one of the most frequently abused features in web applications. A single mistake can let an attacker run code on your server, host malware on your domain, or read files that belong to other customers. This guide covers secure file upload design in practical terms: the mistakes we regularly find in audits, and a layered approach that fixes them.

Why uploads are so risky

An upload feature accepts arbitrary binary content from the internet and stores it on your infrastructure. Depending on how it is built, that content may later be:

  • Executed by the web server.
  • Opened by staff on their computers.
  • Processed by image, PDF or document libraries.
  • Served to other users from your domain.

Each of those is an opportunity for something to go wrong, and each needs its own control.

The most common mistakes

1. Trusting the extension or MIME type

The file name and the Content-Type header both come from the user. Renaming shell.php to shell.php.jpg, or sending a PHP file with an image MIME type, defeats checks that rely on them alone.

2. Storing uploads inside the web root

If files land in a public folder and the server will execute scripts there, an uploaded script becomes a web shell: a remote control for your server. This is one of the most common causes of compromise on PHP sites, including WordPress.

3. Keeping the original file name

User-supplied names can include path traversal sequences such as ../, special characters, or names that overwrite existing files. They also leak personal information when exposed in URLs.

4. Public URLs for private files

Invoices, ID scans and medical documents placed at predictable public URLs can be discovered or guessed. Changing a number in the URL should never reveal another customer's file; this is the broken access control risk described in our OWASP Top 10 plain-language guide.

5. No size or rate limits

Without limits, uploads can fill disks, exhaust memory during processing or be used to run up storage costs.

6. Unsafe processing

Image and document libraries parse complex formats and have had their own vulnerabilities. Archive files can contain huge decompressed payloads ("zip bombs") or paths that write outside the intended folder.

7. Serving files in a way browsers execute

An uploaded HTML or SVG file served from your main domain can run scripts in your visitors' browsers in the context of your site, which enables cross-site scripting.

Key takeaway: Never assume an uploaded file is what it claims to be. Validate it, rename it, store it where it cannot run, and serve it through your own access checks.

A layered approach to secure file upload

No single check is enough. The following layers work together.

Layer 1: decide what you actually accept

Start with business requirements. A careers form may need PDF and DOCX only. A product catalogue needs JPEG, PNG and WebP. A jewellery 3D marketplace may need STL or similar model formats. Write an explicit allow-list per feature; never use a deny-list of "dangerous" types.

Layer 2: validate on the server

  1. Check the extension against the allow-list.
  2. Inspect the file content (magic bytes or a reliable MIME detection library) and confirm it matches an allowed type.
  3. Enforce a maximum size per feature at both the web server and application level.
  4. For images, check dimensions and consider re-encoding them, which strips embedded payloads and metadata.
  5. For archives, limit the number of entries and total decompressed size, and reject paths that escape the target folder.

In Laravel, validation rules such as mimes, mimetypes, max and dimensions cover much of this, provided they are applied on every upload endpoint, including API routes.

Layer 3: store safely

Practice Why
Store outside the public web root, or in private object storage Files cannot be requested or executed directly
Generate a random file name on save Prevents overwriting, traversal and information leaks
Keep the original name only as metadata Displayed safely, never used as a path
Disable script execution in any upload directory Defence in depth if a file ends up public
Encrypt sensitive files at rest Protects data if storage or backups leak
Separate storage per tenant or customer where relevant Limits the impact of access bugs

Layer 4: serve through access control

  • Route downloads through your application, checking that the logged-in user is allowed to access that specific file.
  • Use short-lived signed URLs for object storage instead of permanent public links.
  • Set Content-Disposition: attachment for documents users should download rather than view.
  • Send X-Content-Type-Options: nosniff and an accurate Content-Type.
  • Serve user content from a separate domain or subdomain where practical, so any script in it cannot access your main site's cookies.
  • Log access to sensitive files.

Layer 5: scan and process in isolation

  • Run antivirus or malware scanning on uploads that staff or other users will open.
  • Process images and documents in background jobs with time and memory limits.
  • Keep processing libraries updated; they are part of your supply chain.
  • Quarantine files until scanning completes for high-risk workflows.

Layer 6: limit and monitor

  • Rate-limit uploads per user and per IP.
  • Add bot protection to anonymous upload forms, such as career applications. See bot protection and CAPTCHA alternatives.
  • Monitor storage growth and unusual upload patterns.
  • Alert on files appearing in places they should not, such as executable files in storage folders.

Special cases

Sensitive personal documents

Identity documents, medical reports and financial statements carry legal obligations under privacy laws such as PIPEDA, BC PIPA, the UAE PDPL and the GDPR. Collect them only when necessary, restrict access by role, encrypt them, define retention periods and delete them on schedule. Our guide to protecting health data in web applications covers this in more depth.

Marketplaces selling downloadable files, from design assets to 3D models, need private storage, signed expiring download links, download limits per purchase and watermarking or licensing where appropriate. Our T-Rex commerce engine uses this pattern for digital product delivery.

Admin uploads

Uploads by staff deserve the same validation. A compromised admin account or a malicious file passed on by a supplier can be just as harmful.

A quick checklist for your team

  1. Is there an allow-list of file types for each upload feature?
  2. Is file content checked on the server, not just the extension?
  3. Are files renamed and stored outside the public web root?
  4. Is script execution disabled in every upload location?
  5. Do downloads go through permission checks or signed, expiring URLs?
  6. Are size, count and rate limits enforced?
  7. Are sensitive files encrypted, logged and deleted on schedule?
  8. Are processing libraries kept up to date?

If any answer is "not sure", that is where to look first.

Testing your upload features

Upload handling is easy to get right in one place and wrong in another, so test every endpoint, including API routes and admin screens. A simple test plan includes trying a script file renamed with an image extension, a file with a double extension, an oversized file, a file name containing path characters, and requesting another user's file by changing its identifier. Each should be rejected or denied cleanly, with a helpful error and a log entry.

Next steps

Uploads deserve a focused review in any platform that accepts files from the public or from customers. Most fixes are contained changes, and the risk reduction is significant.

DigiVort designs upload handling into the web applications and SaaS platforms we build and reviews existing systems through our security and compliance service. If you are planning a portal or marketplace that handles files, start a project and we will include a secure upload design from the outset.

Frequently asked questions

Is checking the file extension enough?

No. Extensions and the browser-supplied MIME type are both controlled by the user and easy to fake. Combine an extension allow-list with server-side content inspection, rename files on storage and make sure the storage location cannot execute code.

Should uploaded files be stored in the database?

Usually not. Storing files in object storage or a private disk outside the web root, with metadata in the database, is simpler to scale and back up. The important part is that access goes through your application's permission checks.

Do we need antivirus scanning for uploads?

If files are shared with staff or other users, especially office documents and PDFs, scanning is a sensible extra layer. It will not catch everything, so it complements rather than replaces strict type validation and safe storage.

How should we handle sensitive documents like IDs or medical reports?

Store them privately, encrypt them at rest, restrict access by role, use short-lived download links, log every access and delete them when the retention period ends. Collect them only if you genuinely need them.