← All fixes

Fix it

Insecure file upload — how to fix it

High severityCWE-434 (Unrestricted Upload of File with Dangerous Type)

An upload handler that trusts the file's name and type, and stores it where the server can execute or serve it, is a common path to remote code execution or stored cross-site scripting. Validate the type against an allowlist, give the file a new random name, and store it somewhere it will never be executed.

Why it's a problem

If an attacker can upload a script and then request it, the server may execute it, which is full compromise. Even without execution, an uploaded HTML or SVG file served from your domain can carry cross-site scripting. Trusting the original filename also invites path traversal, writing the file outside the intended folder.

The pattern

// trusts the uploaded name and type
const dest = path.join("public/uploads", file.originalname);
fs.writeFileSync(dest, file.buffer);

The fix

// allowlist type, random name, non-served storage
const allowed = { "image/png": ".png", "image/jpeg": ".jpg" };
const ext = allowed[file.mimetype];
if (!ext) return res.sendStatus(400);
const name = crypto.randomUUID() + ext;
fs.writeFileSync(path.join("/var/uploads", name), file.buffer);

Why AI tools write this

Saving the upload under its original name into a public folder is the most direct way to make an upload feature work and be visible, so it is the natural completion. It works fine for ordinary images in testing, and the danger only appears with a malicious file.

The quick fix

  • Validate the content type against an allowlist; do not trust the file extension alone.
  • Give each upload a new random filename, never the user-supplied one.
  • Store uploads outside the web root so they cannot be executed or directly served.

Want to know if this pattern is already in a repo you shipped? Scan a public repo free, no account needed.

Scan a repo →

Related: related: path traversal

Insecure File Upload — Why It's Dangerous and How to Fix It: Prbl