• Agents
  • Docs
  • Pricing
  • Blog
Log in
Get started

Security for apps built with AI. Paste a URL, get a report, fix what matters.

Product

  • How it works
  • What we find
  • Pricing
  • Agents
  • MCP Server
  • CLI
  • GitHub Action

Resources

  • Blog
  • Docs
  • FAQ
  • Glossary

Security

  • Supabase Security
  • Next.js Security
  • Lovable Security
  • Cursor Security
  • Bolt Security

Legal

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • Imprint
© 2026 Flowpatrol. All rights reserved.
Home/Glossary/Insecure File Upload
CWE-434

Unrestricted Upload (Insecure File Upload)

Insecure file upload is a vulnerability where an application accepts user-uploaded files without properly validating the file type, content, or size. Attackers can exploit this to upload executable scripts, HTML pages containing JavaScript payloads, or massive files that exhaust server resources. It is classified under CWE-434 (Unrestricted Upload of File with Dangerous Type).

What is Insecure File Upload?

Your app has a profile picture upload. An attacker skips the frontend and sends a .html file containing a JavaScript payload directly to your upload endpoint. Your server saves it, serves it back on your domain, and now that script runs in every visitor's browser. That's insecure file upload.

The danger depends on what the server does with the file. If it stores and serves it as-is, an attacker can upload HTML (for XSS), SVGs with embedded scripts, or server-side scripts if the host executes them. Even "just" accepting huge files can take down your app.

CWE-434 covers all of these cases: the server fails to restrict what types of files can be uploaded, how large they can be, or where they end up. It's a deceptively simple bug with a wide blast radius.

How does Insecure File Upload work?

The typical pattern: the upload endpoint reads the file from the request, generates a filename, and writes it to storage — without checking what the file actually is. The client-side file picker might restrict to images, but an attacker never uses the file picker.

Here's a typical vulnerable upload handler:

Vulnerable — no type or size validation
// app/api/upload/route.ts
export async function POST(req) {
  const formData = await req.formData();
  const file = formData.get('file');

  // Problem: accepts any file type, any size.
  // An attacker can upload .html, .svg, or .exe.
  const buffer = Buffer.from(await file.arrayBuffer());
  const filename = file.name;

  await storage.upload(`uploads/${filename}`, buffer);

  return Response.json({
    url: `/uploads/${filename}`,
  });
}
Fixed — MIME validation, extension allowlist, size limit
// app/api/upload/route.ts
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/webp'];
const ALLOWED_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.webp'];
const MAX_SIZE = 5 * 1024 * 1024; // 5 MB

export async function POST(req) {
  const formData = await req.formData();
  const file = formData.get('file');

  // Check file size.
  if (file.size > MAX_SIZE) {
    return Response.json(
      { error: 'File too large' }, { status: 413 },
    );
  }

  // Check MIME type and extension.
  const ext = path.extname(file.name).toLowerCase();
  if (
    !ALLOWED_TYPES.includes(file.type) ||
    !ALLOWED_EXTENSIONS.includes(ext)
  ) {
    return Response.json(
      { error: 'File type not allowed' }, { status: 400 },
    );
  }

  // Use a random filename — never trust the original.
  const safeName = `${crypto.randomUUID()}${ext}`;
  const buffer = Buffer.from(await file.arrayBuffer());

  await storage.upload(`uploads/${safeName}`, buffer);

  return Response.json({ url: `/uploads/${safeName}` });
}

Why do AI tools generate Insecure File Upload vulnerabilities?

When you ask an AI to "add file upload," it generates the shortest path to a working upload. Validation, type checking, and size limits are extras it rarely includes unprompted.

  • Tutorials skip validation for brevity. Most file upload examples in training data focus on getting the file saved. Validation is a "left as an exercise" footnote.
  • Client-side restrictions feel like enough. The model might add <code>accept="image/*"</code> to the file input — but that only filters the file picker, not the API endpoint.
  • Original filenames are used directly. Models rarely generate random filenames. They use <code>file.name</code> as-is, which opens the door to path traversal and file type spoofing.

A working upload and a safe upload are very different things. AI gets you the first one. The second one requires explicit constraints that models skip unless you ask.

Common Insecure File Upload patterns

No server-side type check

The frontend restricts to images, but the API accepts anything — .html, .svg, .php.

User-controlled filenames

Original filename saved as-is — enables path traversal (../../etc/passwd) and overwrites.

No size limit

Uploading a 2 GB file exhausts memory or disk, crashing the server for everyone.

Files served from same origin

Uploaded HTML/SVG files served on your domain execute JavaScript in the context of your app.

How Flowpatrol detects Insecure File Upload

Flowpatrol tests your upload endpoints the way an attacker would — by actually uploading dangerous files and checking what happens:

  1. 1Discovers upload endpoints by crawling your app and observing form submissions and API calls.
  2. 2Uploads test payloads — HTML files with script tags, SVGs with embedded JavaScript, files with spoofed extensions.
  3. 3Checks if the file is served back and whether the browser executes the payload when the uploaded file is accessed.
  4. 4Reports the full chain — upload request, stored file URL, proof of execution, and the fix.

Most scanners check for upload forms but never actually test them. Flowpatrol uploads, fetches, and verifies — proving the bug is real.

Related terms

Cross-Site Scripting (XSS)Directory Traversal (Path Traversal)Sensitive Data Exposure (Information Disclosure)

Check your upload endpoints.

Flowpatrol tests what your file uploads actually accept. Paste your URL and find out.

Try it free