Why this matters
Make the safer upload path obvious.
Inspect the file before storage or downstream processing. That turns uploads from blind trust into an allow, quarantine, or reject decision.
Typical flow
Without Pompelmi
Spoofed files, archive bombs, and risky document structures can slip through this path.
Protected flow
With Pompelmi
This is defense-in-depth for file uploads, not a claim that one library replaces the rest of your security stack.
Protections
What it helps you catch at the upload gate
The core library focuses on the upload gate itself: check what the file claims to be, what the bytes actually show, and whether the structure looks risky before it hits storage.
| Risk | Why it matters | What Pompelmi checks |
|---|---|---|
| Spoofed filesRenamed or mislabeled uploads can bypass basic extension filters. | Client-provided MIME types and filenames are easy to fake. | Extension policy, declared MIME checks, and magic-byte validation. |
| Archive bombs and traversalZIP uploads can hide oversized expansion or unsafe paths. | Archive handling is a common place for resource exhaustion and path abuse. | Entry count, total extracted size, nesting depth, and traversal-oriented archive guards. |
| Risky document structuresSome files look normal on the surface but carry active or suspicious content. | PDF actions, active SVG content, embedded executables, and polyglot files are not visible from the extension alone. | Layered heuristics for risky structures, executable signatures, polyglots, and script-bearing documents. |
| Custom threat patternsYour environment may need narrower or higher-signal detection. | Generic defaults are useful, but some teams need environment-specific rules. | Optional YARA matching as part of a composed scanner pipeline. |
Quick start
One route, one decision
Add one check before storage: inspect the upload, get a verdict, and continue only when the route should trust the file.
import { scanBytes, STRICT_PUBLIC_UPLOAD } from 'pompelmi';
const report = await scanBytes(file.buffer, {
filename: file.originalname,
mimeType: file.mimetype,
policy: STRICT_PUBLIC_UPLOAD,
failClosed: true,
});
if (report.verdict !== 'clean') {
return res.status(422).json({ error: 'Upload blocked', reasons: report.reasons });
} Framework support
Framework support without hiding the core package
Start with the core package or reach for an adapter. The public docs cover the main framework paths first.
Adapters exist for Express, Next.js, NestJS, Fastify, and Koa. The docs also cover a Nuxt/Nitro path.
Trust
What helps teams evaluate it quickly
The public repo includes the surfaces engineers usually look for before adopting a security control.
FAQ
Common questions
Why not just MIME checks or file extensions?
They still help, but they only reflect metadata the client controls or a filename the client chose. Pompelmi adds byte-level and structural inspection before storage.
Does Pompelmi send files to a cloud API?
No. Scanning runs in-process inside your Node.js application. File bytes do not need to leave your infrastructure.
Does it require ClamAV, a sidecar, or another daemon?
No. The built-in heuristics and archive protections work without a daemon. ClamAV and YARA are optional integrations.
Is this a full antivirus replacement?
No. Pompelmi is a defense-in-depth upload gate and risk-reduction layer. It should sit inside a broader security design.
Where does private or commercial support fit?
The MIT-licensed core remains the primary path. Private support exists for rollout help or commercial arrangements when public channels are not a fit. See support options and enterprise support.
Support
Public by default, private when needed
Start with docs, Issues, and Discussions whenever the question can be public. Private rollout help and commercial support are available when needed. See support options or enterprise support.