AI built file upload — avatars, attachments. It works, you shipped. What you actually shipped accepts any file, of any size, and saves it where it can be served back and run.
What you shipped
The handler takes the uploaded file and saves it using the user’s own filename into a public directory, with no check on type or size.

How anyone exploits it
An attacker uploads shell.html (or a script) instead of an image. It lands at /public/shell.html and runs in your domain’s context when opened — stealing sessions or worse. Huge files can also fill your disk and take you down.
Why you won’t catch it
You upload a normal PNG and it works. The dangerous upload only happens when someone sends a file type you didn’t expect — which your own testing never does.
Why AI does it
“Save the upload” most directly becomes saving the file as-is to a public path. Type checks, size limits, and renaming are extra steps the happy path skips.
The fix
Whitelist allowed types, cap the size, and store under a random name outside the executable web root:
allow(file, ['png','jpg']); limitSize(file, '2mb'); save(file, randomName())

Check your app
- Uploads are restricted to an explicit allowlist of types (checked by content, not just extension).
- A maximum size is enforced.
- Files are renamed and served from storage that can’t execute code.
The bigger problem
A senior dev catches this by reflex. But if nobody senior reads the code, the broken version ships — it works in every test, because every test takes the happy path. The author and the reviewer are the same model with the same blind spot.
That’s the gap Velify is built to close: it reads your project and flags exactly this, in plain language, no terminal.
