Your File Upload Endpoint Is Part of Your Attack Surface
Most file upload flows look safe at first glance.
You check the extension.
You validate the Content-Type header.
You set a file size limit.
Then you store the file and move on.
But that is exactly where many applications stay too optimistic.
Real-world upload abuse is not limited to "someone uploaded an .exe". The bigger problem is that modern upload risks often arrive disguised as normal files: ZIP bombs, spoofed MIME types, polyglot files, and documents carrying suspicious embedded behavior.
In many systems, the file gets written to disk, pushed to object storage, backed up, indexed, or passed to another service before meaningful inspection ever happens.
That is the gap I wanted to solve with Pompelmi.
Pompelmi is an open-source file upload scanner for Node.js that runs in-process, with no cloud API and no daemon. The idea is simple: scan untrusted uploads before they touch disk or enter the rest of your pipeline.
That makes file validation part of the application boundary itself, not an afterthought.
Why this matters
A lot of upload security still relies on shallow checks:
- filename extension
- request header MIME type
- basic size validation
Those checks are useful, but they are not enough on their own.
If your application accepts PDFs, images, Office documents, or archives, you are already dealing with a richer attack surface than many teams realize. ZIP nesting, misleading MIME data, and suspicious embedded content are all things that can slip through simplistic validation.
The real shift is architectural:
Don't treat upload security as a storage problem.
Treat it as an entry-point problem.
If you wait until after persistence, the file may already have spread across systems you now need to clean up.
What I wanted from a Node.js solution
When I built Pompelmi, I wanted a solution that felt native to the Node ecosystem:
- installable like a normal npm package
- TypeScript-first
- easy to plug into existing frameworks
- privacy-friendly by default
- usable without sending files to third parties
That led to a design centered on a few practical ideas:
- scan bytes locally, in-process
- block early
- combine heuristics and optional YARA-based detection
- support common Node.js frameworks directly
- keep the same scanning contract across adapters
What Pompelmi does
At a high level, Pompelmi gives you a security layer for file uploads with features such as:
- content-aware MIME validation
- extension allow-lists
- file size policies
- ZIP deep inspection with nesting and expansion limits
- optional YARA integration
- composable scanners
- framework adapters for Express, Koa, Next.js, and NestJS
- a GitHub Action for scanning files or artifacts in CI/CD pipelines
That combination matters because different teams need different tradeoffs.
Some only want sane upload policies.
Some want deeper archive inspection.
Some want custom signature logic.
Some want CI coverage in addition to runtime protection.
The developer experience was a big priority
Security tools often become hard to adopt when they introduce too much operational overhead.
That is why one of the most important design choices in Pompelmi is what it does not require:
- no sidecar service
- no separate daemon
- no cloud scanning API
- no API keys just to get started
For many teams, especially privacy-sensitive ones, that is not a small detail. It changes adoption completely.
If your application handles internal documents, customer uploads, or regulated data, keeping scanning local can be the difference between "maybe later" and "we can ship this now".
Example: protecting an Express upload route
A typical integration can stay very close to the upload flow you already have.
import express from "express";
import multer from "multer";
import { createUploadGuard } from "@pompelmi/express-middleware";
import { CommonHeuristicsScanner } from "pompelmi";
const app = express();
const upload = multer({ storage: multer.memoryStorage() });
app.post(
"/upload",
upload.any(),
createUploadGuard({
includeExtensions: ["pdf", "png", "jpg", "zip"],
maxFileSizeBytes: 10 * 1024 * 1024,
scanners: [CommonHeuristicsScanner],
}),
(_req, res) => {
res.json({ ok: true });
}
);
The important part is not the syntax.
The important part is where the decision happens: before the file is allowed deeper into your system.
That is the architectural win.
Security tooling should fit real workflows
One thing I care about a lot is avoiding "demo-only security".
A security tool is only useful if it fits how teams actually build software. That means:
- app-level integration
- framework compatibility
- predictable verdicts
- documentation
- CI support
- room for custom detection logic
Pompelmi was designed around that idea.
It can be used as a standalone Node.js library, through framework adapters, or in build pipelines through its GitHub Action. It also supports a composable model where heuristics and YARA-based scanners can be combined behind a shared interface.
Open source, but built for real adoption
Another thing I wanted was to keep the project open and transparent while still making it useful for teams that need help adopting it.
That is why the project has public docs, a live demo, community support channels, and a lightweight commercial support path for private async help.
To me, that is an important part of modern open source: not just publishing code, but reducing friction for people who want to use it seriously.
Final thought
If your Node.js application accepts file uploads, your upload route is not just a convenience feature.
It is a trust boundary.
And trust boundaries deserve better than extension checks and optimism.
That is the problem I built Pompelmi for.
If you are working on secure uploads in Node.js, I would genuinely love feedback on the approach, the API design, and the threat model behind it.
- GitHub: https://github.com/pompelmi/pompelmi
- Website: https://pompelmi.github.io/pompelmi/
Top comments (0)