feat: add secure file upload with virus scanning via pompelmi#316
feat: add secure file upload with virus scanning via pompelmi#316Gauravkachwaha wants to merge 3 commits into
Conversation
|
Hey @Gaurav8957999847, thanks for implementing this so cleanly! A few small things before we merge: 1. Timeout — if clamd is unreachable, scanBytes will hang. const report = await scanBytes(req.file.buffer, {
host: STRICT_PUBLIC_UPLOAD.host,
port: STRICT_PUBLIC_UPLOAD.port,
timeout: 5000
});2. Error handling — if clamd is down, scanBytes throws. try {
const report = await scanBytes(req.file.buffer, options);
} catch (err) {
return res.status(503).json({
message: 'Virus scanner unavailable — try again later'
});
}3. Handle ScanError verdict — pompelmi returns three verdicts: if (report.verdict === Verdict.ScanError) {
return res.status(422).json({
message: 'Scan incomplete — file rejected as precaution'
});
}4. README prerequisite — add a note that clamd must be running Everything else looks great. Happy to approve once these are in! 🍊 |
|
Hi @hagopj13 , just following up on this PR. The requested changes have been addressed, and @SonoTommy has left an approving review saying the timeout handling, ScanError verdict handling, and README prerequisite note look correct. Please let me know if anything else is needed from my side before merge. |
Summary
Adds a secure file upload endpoint (
POST /v1/upload) with virus scanning viapompelmi.Builds on the earlier upload discussion in #204 and implements the secure-by-default approach proposed in #312.
Changes
src/controllers/upload.controller.js— scans file buffer usingscanBytes()before acceptingsrc/routes/v1/upload.route.js—multer.memoryStorage(), MIME type allowlist, and file size validationsrc/validations/upload.validation.js— validation schema following existing patternsrc/routes/v1/index.js— registered/uploadroutetests/integration/upload.test.js— added integration tests for clean, malicious, suspicious, and invalid upload casesSecurity Approach
memoryStorage()so files never touch disk before scanningscanBytes()runs in-process with no external API callsfailClosed: true)Closes #312