Q20 of 24 · Security
How do you test file upload functionality for security vulnerabilities?
SecuritySeniorsecurityfile-uploadpath-traversalcontent-typeowasptestingsenior
Short answer
Short answer: Test: uploading a file with a mismatched extension and Content-Type, an executable disguised as an image, a filename containing path traversal sequences, a file exceeding the size limit, and a file with malicious content (polyglot). Verify uploaded files are served from a separate non-executable domain or storage, not from the application server.
Detail
File upload is one of the richest attack surfaces in web applications. A QA test plan should cover:
Content-type validation:
- Upload an executable (
.php,.jsp,.exe,.sh) with the Content-Type set toimage/jpeg. - Upload a valid-looking JPEG file that contains embedded executable content (a JPEG/PHP polyglot).
- Assert: both are rejected, or are stored without execute permissions and served with a safe Content-Type.
Extension validation:
- The server must validate the file extension server-side, not rely on the Content-Type header (which the client controls).
- Bypass attempts:
evil.php%00.jpg(null byte truncation — older servers may strip the .jpg suffix),evil.phtml,evil.PHP(case variation).
Filename path traversal:
- Submit a filename containing
../../../etc/passwdor..\..\Windows\System32\. - Assert: the server sanitises the filename and stores it safely, it does not save the file at the traversal path, and the response does not reveal server-side file system structure.
Size limits:
- Upload a file that exceeds the configured maximum size.
- Assert: rejected with a 413 Payload Too Large before server-side processing completes (important for DoS prevention — the server should not process a 10 GB file before checking the limit).
Storage validation:
- After a successful upload, retrieve the file URL. Verify the URL does not serve from the application server (which might execute PHP/JSP files). Files should be served from a CDN or object storage (S3, GCS) with no execution capability.
// EXAMPLE
file-upload-security.test.ts
test('rejects executable files disguised as images', async ({ request }) => {
const evilContent = Buffer.from('<?php system($_GET["cmd"]); ?>');
const response = await request.post('/api/upload', {
multipart: {
file: {
name: 'photo.jpg',
mimeType: 'image/jpeg',
buffer: evilContent,
},
},
});
// Must reject — not accept and serve
expect([400, 415, 422]).toContain(response.status());
});// WHAT INTERVIEWERS LOOK FOR
Covers content-type mismatch, extension bypass, path traversal, size limits, and storage validation as distinct test cases. Notes files must not be served from the application server.