---
title: Handle uploads as untrusted input
description: >-
  Treat every uploaded file as untrusted input: validate it, rename it, store it
  outside your app, serve it with explicit headers, and re-encode images.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/security/backend/handle-uploads-as-untrusted-input
  md: >-
    https://shopify.dev/docs/apps/build/security/backend/handle-uploads-as-untrusted-input.md
---

# Handle uploads as untrusted input

Treat every uploaded file as untrusted input, the same as any text field.

***

## Why

An uploaded file can carry code. An SVG is an XML document that can contain `<script>` elements, event handler attributes, and external entity references, and browsers run all of it when the file is served as `image/svg+xml` and loaded directly.

***

## How

Apply all of the following to every upload path, including ones that only staff use:

* Validate size, extension, declared MIME type, and the actual file signature, and require them to agree. File type detection can be bypassed, so combine this step with the ones below.
* Generate the stored filename yourself. Never use supplied filenames as identifiers. Store them as metadata instead.
* Store uploads outside any directory that your application serves or executes from. Use hosted object storage.
* Serve files with an explicit `Content-Type` and `Content-Disposition`, so that attackers can't chain a malicious file with a vulnerability in client code.
* Re-encode images through a trusted processing pipeline rather than storing the original bytes. Re-encoding drops embedded payloads as a side effect of rewriting the pixels. Managed image services can do this for you.
* Reject SVG, XML, and HTML uploads unless your product truly requires them. If it does, then sanitize them and serve them from a separate origin, so they can't reach your session cookies.

***
