A file upload handler without a size limit is a direct path to disk exhaustion and runaway cloud storage costs — a single malicious actor can POST a 50 GB file to your server, filling disk and triggering overage charges before any alert fires. This maps to CWE-770 and OWASP A05:2021 (Security Misconfiguration): the absence of a limit is a misconfiguration at the application layer, independent of what a CDN or load balancer might reject. Platforms like Vercel enforce a 4.5 MB body limit by default, but self-hosted or Docker deployments carry no such protection. A successful attack disrupts all users on the same host, not just the attacker.
Critical because a single oversized upload can fill disk, crash the process, and block all other users on the same host with no application-level defense.
Set maxFileSize at library initialization, not as a post-read check. Validating size after reading defeats the purpose — the damage is done once the bytes hit memory.
import formidable from 'formidable'
export async function POST(req: Request) {
const form = formidable({
maxFileSize: 10 * 1024 * 1024, // 10 MB hard cap
maxFiles: 1,
})
// formidable will throw a 413 automatically if the limit is exceeded
const [, files] = await form.parse(req as any)
// ...
}
For Next.js Route Handlers using request.formData(), check file.size immediately: if (file.size > 10 * 1024 * 1024) return Response.json({ error: 'File too large' }, { status: 413 }).
ID: ai-slop-cost-bombs.unbounded-operations.file-upload-size-limit
Severity: critical
What to look for: Walk all API handlers and count all handlers that process file uploads. A file upload handler is one that uses formidable, multer, busboy, @vercel/blob/client, @aws-sdk/lib-storage, OR calls request.formData() / req.body and reads file content. For each file upload handler, before evaluating, extract and quote the relevant configuration line — quoting the exact configuration is required for accurate evaluation. Verify the handler includes one of these size-limit configurations: maxFileSize, limits: { fileSize: ... }, maxBodyLength, bodyParser.json({ limit: ... }), multer({ limits: { fileSize: ... } }), OR a manual size check on the file before processing. EXCLUDE size limits set at the platform level (Vercel max body 4.5MB, Cloudflare max upload 100MB) — those are out of scope for this check.
Pass criteria: 100% of file upload handlers configure a max file size at the application level via maxFileSize, limits.fileSize, bodyParser.json({ limit }), OR an explicit manual size check before processing the file content.
Report even on pass: Always report the count and the smallest size limit found. Example: "3 file upload handlers inspected, all 3 enforce max size (smallest: 5 MB)."
Fail criteria: At least 1 file upload handler has no application-level size limit.
Do NOT pass when: Size limit is set to 1 GB or higher — that's effectively no limit.
Skip (N/A) when: Project has 0 API handlers that process file uploads (no upload-library imports AND no formData()/req.body file handling found).
Detail on fail: "1 unbounded file upload: app/api/upload/route.ts uses formidable() with no limits — accepts files of any size, will fill disk and run up egress costs"
Remediation: A file upload endpoint with no size limit lets one user fill your entire disk with a single request. Always set a max file size:
// Bad: no limit
import formidable from 'formidable'
const form = formidable() // any size accepted
// Good: 10 MB cap
import formidable from 'formidable'
const form = formidable({
maxFileSize: 10 * 1024 * 1024, // 10 MB
maxFiles: 1,
})
For Next.js Route Handlers using request.formData(), validate file.size manually before reading: if (file.size > 10 * 1024 * 1024) return Response.json({ error: 'Too large' }, { status: 413 }).