Comprehensive Pompelmi file upload security scanning commands for Node.js application protection.
Installation
| Command | Description |
|---|
npm install pompelmi | Install Pompelmi via npm |
yarn add pompelmi | Install Pompelmi via Yarn |
pnpm add pompelmi | Install Pompelmi via pnpm |
bun add pompelmi | Install Pompelmi via Bun |
Basic Setup (Express)
const express = require('express');
const { createScanner } = require('pompelmi');
const app = express();
const scanner = createScanner({
maxFileSize: '10mb',
allowedExtensions: ['.pdf', '.png', '.jpg', '.docx'],
});
app.post('/upload', scanner.middleware(), (req, res) => {
res.json({ files: req.files });
});
Framework Adapters
| Framework | Description |
|---|
pompelmi/express | Express.js middleware adapter |
pompelmi/koa | Koa middleware adapter |
pompelmi/next | Next.js API route adapter |
pompelmi/nitro | Nuxt/Nitro adapter |
pompelmi/fastify | Fastify plugin adapter |
Scanner Configuration
| Option | Description |
|---|
maxFileSize: '10mb' | Maximum allowed file size |
allowedExtensions: ['.pdf', '.png'] | Whitelist of allowed file extensions |
blockedExtensions: ['.exe', '.bat'] | Blacklist of blocked extensions |
allowedMimeTypes: ['image/png'] | Whitelist of allowed MIME types |
scanTimeout: 30000 | Scan timeout in milliseconds |
tempDir: '/tmp/pompelmi' | Temporary directory for scanning |
preserveOriginalName: true | Keep original filename |
YARA Integration
| Option | Description |
|---|
yara: { enabled: true } | Enable YARA rule scanning |
yara: { rules: './rules/' } | Path to custom YARA rules directory |
yara: { builtinRules: true } | Use built-in malware detection rules |
yara: { timeout: 10000 } | YARA scan timeout |
| Custom YARA rules file | Write .yar files for custom detection |
Archive Protection
| Option | Description |
|---|
archive: { enabled: true } | Enable archive inspection |
archive: { maxDepth: 3 } | Maximum recursion depth for nested archives |
archive: { maxFiles: 100 } | Maximum files inside archive |
archive: { maxRatio: 100 } | Max compression ratio (zip bomb protection) |
archive: { maxSize: '100mb' } | Max total extracted size |
archive: { formats: ['zip', 'tar', 'gz'] } | Supported archive formats |
Security Policies
| Policy | Description |
|---|
policy: 'strict' | Block anything suspicious (recommended) |
policy: 'moderate' | Block known malware, warn on suspicious |
policy: 'permissive' | Only block confirmed malware |
| Custom policy function | Define your own accept/reject logic |
MIME Type Validation
| Check | Description |
|---|
| Extension validation | Check file extension against allowlist |
| Magic byte detection | Verify file type by content bytes |
| MIME type verification | Server-side MIME type checking |
| Double extension detection | Catch file.pdf.exe tricks |
| Null byte detection | Block null byte injection in filenames |
| Content-Type mismatch | Detect extension/content mismatches |
Event Hooks
| Event | Description |
|---|
scanner.on('scan:start', fn) | Fired when scan begins |
scanner.on('scan:complete', fn) | Fired when scan finishes |
scanner.on('scan:reject', fn) | Fired when file is rejected |
scanner.on('scan:accept', fn) | Fired when file passes all checks |
scanner.on('scan:error', fn) | Fired on scanning error |
scanner.on('yara:match', fn) | Fired when YARA rule matches |
Scan Results
| Property | Description |
|---|
result.safe | Boolean: file passed all checks |
result.threats | Array of detected threats |
result.mimeType | Detected MIME type |
result.extension | File extension |
result.size | File size in bytes |
result.hash | SHA-256 hash of file |
result.scanTime | Time taken to scan (ms) |
result.yaraMatches | YARA rule matches (if enabled) |
Express Middleware Example
const { createScanner } = require('pompelmi');
const scanner = createScanner({
maxFileSize: '5mb',
allowedExtensions: ['.pdf', '.png', '.jpg'],
yara: { enabled: true, builtinRules: true },
archive: { enabled: true, maxDepth: 2 },
policy: 'strict',
});
// As middleware
app.post('/upload', scanner.middleware(), handleUpload);
// Manual scanning
app.post('/upload', async (req, res) => {
const result = await scanner.scan(req.file.buffer, {
filename: req.file.originalname,
});
if (!result.safe) {
return res.status(400).json({
error: 'File rejected',
threats: result.threats,
});
}
// Process safe file...
});
Koa Adapter Example
const { createScanner } = require('pompelmi/koa');
const scanner = createScanner({
maxFileSize: '10mb',
allowedMimeTypes: ['application/pdf', 'image/*'],
});
router.post('/upload', scanner.middleware(), async (ctx) => {
ctx.body = { files: ctx.request.files };
});
Next.js API Route Example
import { createScanner } from 'pompelmi/next';
const scanner = createScanner({
maxFileSize: '5mb',
allowedExtensions: ['.pdf', '.png'],
});
export default scanner.handler(async (req, res) => {
const files = req.files;
res.json({ uploaded: files.length });
});
CLI Scanning
| Command | Description |
|---|
npx pompelmi scan <file> | Scan a single file |
npx pompelmi scan ./uploads/ | Scan directory of files |
npx pompelmi scan --yara <file> | Scan with YARA rules |
npx pompelmi scan --json <file> | Output results as JSON |
npx pompelmi rules list | List available YARA rules |
npx pompelmi rules update | Update built-in YARA rules |
Tips and Best Practices
| Tip | Description |
|---|
| Use strict policy in production | Reject anything suspicious |
| Enable YARA rules | Detect known malware signatures |
| Set archive limits | Prevent zip bombs and nested payloads |
| Validate MIME types server-side | Don’t trust client Content-Type |
| Check double extensions | Block file.pdf.exe patterns |
| Set reasonable size limits | Prevent resource exhaustion |
| Scan in memory | Avoid writing untrusted files to disk |
| Monitor scan events | Log and alert on rejections |
| Update YARA rules regularly | Stay current with threat intelligence |
| Use allowlists over blocklists | Whitelisting is safer than blacklisting |