Add file upload route with built-in security scanning (multer + pompelmi)
Add file upload route with built-in content scanning
This picks up where issue #204 left off. That issue proposed adding file upload via multer, which makes sense. This issue proposes adding it with security scanning built in from the start, so the boilerplate ships with a safe default rather than a bare upload route that developers have to secure themselves.
Why secure-by-default matters here
A boilerplate is copied and deployed as-is more often than it should be. If the upload route ships without content inspection, every project based on this boilerplate inherits the same gap:
- MIME spoofing: a file named
document.pdfwith a malicious payload passes extension and client-reported MIME checks - ZIP bombs: a compressed file that expands to exhaust memory or disk during later processing
- Office macros / active PDF content: macro-enabled files or PDFs with embedded JavaScript actions
- Polyglot files: valid in multiple formats simultaneously, bypass type-based routing
These are not theoretical — they are the most common real-world upload attack vectors.
Proposed implementation
Add a /upload route using multer (memoryStorage, not diskStorage — scan before touching disk) with pompelmi as the scan step:
const multer = require('multer');
const { scanBytes, STRICT_PUBLIC_UPLOAD } = require('pompelmi');
const upload = multer({ storage: multer.memoryStorage() });
router.post('/upload', auth(), upload.single('file'), async (req, res) => {
const report = await scanBytes(req.file.buffer, {
filename: req.file.originalname,
mimeType: req.file.mimetype,
policy: STRICT_PUBLIC_UPLOAD,
failClosed: true,
});
if (report.verdict !== 'clean') {
return res.status(422).json({
code: httpStatus.UNPROCESSABLE_ENTITY,
message: `Upload blocked: ${report.reasons.join(', ')}`,
});
}
// proceed to storage (S3, disk, etc.)
res.status(200).json({ message: 'File accepted', filename: req.file.originalname });
});This uses memoryStorage intentionally: the file is scanned in-process before any write to disk or cloud storage. pompelmi runs with zero external API calls — no cloud service, no daemon, files never leave the process.
Scope of the PR I can submit
- New
upload.route.js+upload.controller.jsfollowing the existing project structure - Validation middleware for file type and size using the existing
validatepattern - Tests following the existing Mocha/chai/supertest pattern
- README section documenting the upload endpoint
Happy to submit the PR immediately — let me know if the scope looks right or if you'd prefer a narrower starting point.
References
- Picks up from: #204
- pompelmi repo: https://github.com/pompelmi/pompelmi
- License: MIT
- Coverage: Node Weekly #594, Help Net Security, Stack Overflow Blog
Source: hagopj13/node-express-boilerplate