Safeguard
Application Security•

Why does a vibe-coded Node.js file upload API end up vulnerable?

AI-generated upload code often works on the first try and skips the checks that matter. Review type, name, size, storage and permissions before you ship.

Safeguard Security Team
4 min read

A vibe-coded Node.js file upload API is often vulnerable because generated code optimizes for "the upload works," not for hostile input. The usual gaps are trusting the file name and type, storing files in a web-served folder, setting no size limits, and skipping access checks. Review each before shipping.

What does the typical generated code look like?

Ask an assistant for an upload endpoint and you commonly get a middleware that saves the file under its original name into a public uploads folder, with a quick check on the file extension. It runs, the demo works, and the code gets committed. Nothing in the demo tests what happens when someone uploads something unexpected.

The OWASP File Upload Cheat Sheet organizes the real checklist, and its section headings read like the missing pieces: content type validation, file signature validation, filename safety, file content validation, storage location, user permissions, filesystem permissions, and upload and download limits.

Which flaws show up most?

  1. Trusting the client's file name. A name containing path segments can write outside the intended folder, which is the path traversal weakness tracked as CWE-22.
  2. Trusting the declared content type. That header comes from the client, and the client controls it.
  3. Checking only the extension. An extension says little about what is inside the file.
  4. Storing uploads where the web server will serve or run them. A file the server treats as executable becomes code execution.
  5. No size or count limits, which invites storage exhaustion and slow request attacks.
  6. No authorization. Any caller can upload, list or fetch any file, or fetch another user's file by changing an ID.
  7. Returning the stored path or serving files inline with their original type, which can lead to script execution in a browser.

What does the cheat sheet recommend?

In summary: allow only the extensions your business needs, validate the content type and file signature instead of trusting the header, generate a new file name rather than using the user's, store files outside the web root or on a separate storage service, set limits on size, and run the application with least privilege on the file system. Scan content where it matters, for example with malware scanning for documents shared among users.

A constructed example

A prompt asks for "an endpoint to upload profile pictures." The result accepts any file, keeps the original name, and writes to a public folder. A tester uploads a file named with path segments and a script extension. Depending on the server, it overwrites a file or lands somewhere it can be requested and run. The corrected version accepts only two image types, checks the file signature, assigns a random name, stores it in object storage, caps size at a few megabytes, and serves it from a different domain with a fixed image type. The endpoint is also limited to authenticated users, and each user can fetch only their own files.

Why does this keep happening?

Models reproduce common code, and common code is full of tutorials that stop at "it works." A reviewer who also reads quickly may approve it because tests pass. The fix is to give the review a checklist and to automate part of it.

How to check or apply this

  1. Write the requirements first: which file types, maximum size, who may upload, who may read.
  2. Generate a random storage name and keep the original only as metadata, after cleaning it.
  3. Validate the file signature and the content type against an allowlist.
  4. Store outside the web root, or in a storage service with no execute rights.
  5. Add size limits at both the proxy and the application.
  6. Enforce authorization on every download, not only on upload.
  7. Add negative tests: wrong type, oversized file, path characters in the name, another user's ID.
  8. Run static analysis and dependency scanning in CI on generated code like any other code.

Safeguard's IDE extensions and CLI can scan code and dependencies as the assistant writes it, so the review has evidence in front of it.

Quick check

Is checking the file extension enough?

No. Extensions are easy to fake. Validate the signature and the content type, and store the file so it cannot run.

Should I trust the Content-Type header?

No. The client sets it. Treat it as a hint and verify the content.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.