A file upload endpoint that validates only the file extension. Find the inputs that slip past the allowlist — a renamed executable, an empty file, and a filename carrying a stored XSS payload.
File upload endpoints enforce several independent checks: extension allowlist, MIME type validation, size limit, and filename sanitization. Failing any one is a distinct bug. The most dangerous case is checking only the extension — a .exe renamed to .jpg passes the allowlist but its declared MIME type reveals it is not an image. Empty files and unsanitized filenames are also common oversights.
| True Positive | photo.jpg valid JPEG, 500 KB — accepted correctly |
| True Positive | large.png valid PNG, 3 MB — rejected by the size limit |
| Bug Found | shell.jpg with MIME type application/x-msdownload — MIME type not validated (extension-only check) |
| Bug Found | empty.jpg 0 bytes — empty file check missing |
| Bug Found | <script>alert(1)</script>.jpg — filename stored and rendered without HTML encoding (stored XSS) |
Validates the file extension only. MIME type is accepted as-is from the request. No empty-file guard. Filename stored without sanitization.
✗ Extension check onlyValidates extension, cross-checks the declared MIME type against the extension, rejects empty files, and sanitizes the filename before storage. Try the same payloads.
✓ Extension + MIME + size + filename sanitizationphoto.jpg, MIME image/jpeg, 512000 bytes on Endpoint A — valid file accepted on both endpoints (true positive)large.png, MIME image/png, 3200000 bytes on Endpoint A — exceeds the 2 MB limit, correctly rejected (true positive)shell.jpg, MIME application/x-msdownload, any non-zero size on Endpoint A — the .jpg extension passes the allowlist but the executable MIME type is ignored (bug found). Same input on Endpoint B is rejected by the MIME check (true positive)image/jpeg, size 0 on Endpoint A — empty files are not guarded against (bug found). Endpoint B rejects them explicitly (true positive)<script>alert(1)</script>.jpg, MIME image/jpeg, any size on Endpoint A — the filename is stored unescaped and would execute in any browser rendering the file listing (bug found). Endpoint B sanitizes the characters before storage (true positive)