How to Pass a Penetration Test File Upload Check
Your application just failed a penetration test. The finding reads something like: "The application accepted a known malicious file without detection." The tester uploaded an EICAR test file, your app stored it without complaint, and now there's a line item in the report that needs fixing before the next retest.
This is one of the most common findings we see. It comes straight from the OWASP Web Security Testing Guide, specifically section 10.09: "Test Upload of Malicious Files." The good news is it's straightforward to fix.
What the Tester Actually Did
Penetration testers follow a standard playbook for file upload checks. Here's what they typically test:
- Upload a known malicious file — usually the EICAR test file, a harmless file that every antivirus engine agrees to detect
- Upload files with mismatched extensions — rename a
.exeto.jpgand see if the app accepts it - Upload files with embedded payloads — Office documents with macros, PDFs with JavaScript, archives containing executables
- Bypass client-side validation — disable JavaScript or modify the request to skip any browser-based checks
- Check if uploaded files are served to other users — can another user download the malicious file?
If your application accepted any of these without flagging them, that's a finding. The severity depends on whether the file can reach other users or systems.
Why File Type Validation Isn't Enough
The first instinct is usually to add more validation — check MIME types, verify file extensions, maybe inspect magic bytes. This helps, but it doesn't address the core finding.
Pen testers aren't testing whether your app checks file extensions. They're
testing whether your app detects known malware. A .pdf that passes every
type check can still contain an exploit. A .docx with valid headers can carry
a macro payload. The EICAR file itself is a valid DOS executable — its file
type is legitimate.
You need actual malware scanning: running files against detection engines that recognise malicious content regardless of the file's type or extension.
The Fix: Add Malware Scanning
The fix is to scan every uploaded file against malware detection engines before it's stored or served. With AttachmentScanner, this is a single API call:
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.attachmentscanner.com/eicar.com"}' \
-XPOST https://YOUR_API_URL/v1.0/scans
{
"status": "found",
"filename": "eicar.com",
"matches": ["Eicar-Test-File-Signature"]
}
A status of found means the file was detected. Your application blocks it,
the tester's check passes, and the finding is resolved.
For a full walkthrough of integrating scanning into your upload flow — including sync vs async patterns and staging areas — see our complete guide to scanning user uploads.
Setting Up for the Retest
To make sure you pass the retest, you need to verify your integration catches the same files the tester will use. Here's a checklist:
1. Test with EICAR
Every pen tester uses the EICAR test file. It's the standard — if your scanning doesn't catch EICAR, it won't catch anything.
We host a copy at https://www.attachmentscanner.com/eicar.com. Scan it
through your application the same way a user would upload a file:
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.attachmentscanner.com/eicar.com"}' \
-XPOST https://YOUR_API_URL/v1.0/scans
You should get "status": "found". If you get "status": "ok", your
integration isn't wired up correctly.
2. Test with EICAR in Archives
Testers often embed the EICAR string inside ZIP files, GZIP archives, or nested containers to see if your scanning handles compressed content. AttachmentScanner's engines detect EICAR inside archives automatically — but test it yourself to be sure.
3. Test with Mismatched Extensions
Rename a file and upload it. Your scanning should detect malicious content regardless of the file extension. This is about the scanning engines inspecting the actual content, not trusting the filename.
4. Verify Files Are Blocked or Quarantined
It's not enough to scan — your application needs to act on the result. The tester will check whether the malicious file is accessible after upload. Make sure:
- Files with
status: "found"are rejected or quarantined - Files with
status: "pending"are not served until scanning completes - Files with
status: "warning"(macros, encrypted archives) are handled according to your policy
5. Test the User-Facing Flow
Don't just test the API — test the full upload flow through your application's UI. The tester will use your application the way a user would. Make sure scanning is triggered regardless of how the file arrives.
The Recommended Architecture
For pen test compliance, we recommend async scanning with a staging area. Something like this:
// Upload handler — returns immediately
async function handleUpload(req, res) {
const stagedPath = await storeInStaging(req.file);
await fetch(`https://${API_URL}/v1.0/scans`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: presignedUrlFor(stagedPath),
callback: "https://your-app.com/webhooks/scan-complete",
async: true,
}),
});
return res.status(202).json({ status: "processing" });
}
// Callback handler
async function handleScanCallback(req, res) {
const result = req.body;
if (result.status === "ok") {
await moveToUploads(result.url);
} else if (result.status === "found") {
await moveToQuarantine(result.url, result.matches);
await notifyAdmin(result);
} else if (result.status === "warning") {
await flagForReview(result.url, result.matches);
}
return res.status(200).end();
}
This approach gives you:
- No unscanned files served — files stay in staging until confirmed clean
- Audit trail — quarantined files can be reviewed and reported on
- Evidence for the tester — you can demonstrate that malicious uploads are caught and quarantined
- Non-blocking uploads — your app isn't tied up waiting for scan results
Common Pen Test Findings and How to Address Them
"Application accepted EICAR test file"
Fix: Add malware scanning to your upload flow. Scan every file before storing or serving it.
"Malicious file was accessible to other users after upload"
Fix: Files must not be served until scanning completes. Use a staging area and only move files to the public location after a clean scan result.
"Application only performs client-side validation"
Fix: Client-side validation is easily bypassed. All scanning and validation must happen server-side.
"Application accepts files with mismatched extensions"
Fix: Don't rely on file extensions for security. Malware scanning inspects actual file content regardless of the filename.
"No scanning of archived/compressed content"
Fix: AttachmentScanner's engines scan inside archives (ZIP, GZIP, etc.) automatically. Verify this with an EICAR file inside a ZIP.
"Uploaded macros/scripts not detected"
Fix: AttachmentScanner returns a warning status for files containing
macros or encrypted archives. Decide on a policy — block them, quarantine them
for review, or allow them based on your use case.
What to Include in Your Retest Evidence
When the tester comes back, having documentation ready speeds things up:
- Architecture diagram showing the scanning flow (staging → scan → move/quarantine)
- Test results demonstrating EICAR detection through your application
- Code showing how scan results are handled (reject, quarantine, etc.)
- Logs showing quarantined files from your own testing
- Policy documentation for how you handle
warningstatus files
Getting Started
- Sign up for an account — you'll get an API token and endpoint URL
- Test with the EICAR test file to confirm detection works
- Integrate async scanning with callbacks into your upload flow
- Run through the retest checklist before the tester returns
Most developers have this fixed within an hour. If you've got a retest coming up and need help, get in touch — we're happy to help you get it sorted.
AttachmentScanner Team
Other Articles
Scanning User Uploads for Malware
AttachmentScanner Team
A Fresh New Look
AttachmentScanner Team
AWS S3 Antivirus Protection
AttachmentScanner Team