pompelmi 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,26 @@
1
+ <div align="center">
2
+
3
+ <!-- Language Selector -->
4
+ <p>
5
+ <strong>Read this in other languages:</strong><br/>
6
+ <a href="docs/i18n/README.it.md">🇮🇹 Italiano</a> •
7
+ <a href="docs/i18n/README.fr.md">🇫🇷 Français</a> •
8
+ <a href="docs/i18n/README.es.md">🇪🇸 Español</a> •
9
+ <a href="docs/i18n/README.de.md">🇩🇪 Deutsch</a> •
10
+ <a href="docs/i18n/README.ja.md">🇯🇵 日本語</a> •
11
+ <a href="docs/i18n/README.zh-CN.md">🇨🇳 简体中文</a> •
12
+ <a href="docs/i18n/README.ko.md">🇰🇷 한국어</a> •
13
+ <a href="docs/i18n/README.pt-BR.md">🇧🇷 Português</a> •
14
+ <a href="docs/i18n/README.ru.md">🇷🇺 Русский</a> •
15
+ <a href="docs/i18n/README.tr.md">🇹🇷 Türkçe</a>
16
+ </p>
17
+
18
+ > 💡 **Translation Note:** Help improve translations by opening a PR. The English README is the source of truth.
19
+
20
+ </div>
21
+
22
+ ---
23
+
1
24
  <!-- HERO START -->
2
25
 
3
26
  <p align="center">
@@ -14,21 +37,33 @@
14
37
  <a href="https://bytes.dev/archives/429"><img alt="Featured in Bytes #429" src="https://img.shields.io/badge/featured-Bytes%20%23429-111111"></a>
15
38
  <a href="https://dev.to/sonotommy/secure-nodejs-file-uploads-in-minutes-with-pompelmi-3jfe"><img alt="Featured on DEV.to" src="https://img.shields.io/badge/featured-DEV.to-0A0A0A?logo=devdotto"></a>
16
39
  <br/>
40
+ <a href="https://github.com/sorrycc/awesome-javascript"><img alt="Mentioned in Awesome JavaScript" src="https://awesome.re/mentioned-badge.svg"></a>
41
+ <a href="https://github.com/dzharii/awesome-typescript"><img alt="Mentioned in Awesome TypeScript" src="https://awesome.re/mentioned-badge-flat.svg"></a>
42
+ <br/>
17
43
 
18
44
  </p>
19
45
 
20
46
  <h1 align="center">pompelmi</h1>
21
47
 
48
+ <p align="center">
49
+ <strong>Fast, Private, and Powerful File Malware Scanning for Node.js</strong>
50
+ </p>
22
51
 
52
+ <p align="center">
53
+ ⚡ Zero-config setup • 🔒 Privacy-first • 🧩 Composable scanners • 📦 Deep ZIP inspection • 🎯 Framework adapters
54
+ </p>
23
55
 
24
56
  <p align="center">
57
+ <strong>YARA</strong> integration • <strong>ZIP bomb</strong> protection • Drop-in middleware for <strong>Express</strong>, <strong>Koa</strong>, <strong>NestJS</strong>, <strong>Fastify</strong>, and <strong>Next.js</strong> • <strong>CLI</strong> for CI/CD
58
+ </p>
25
59
 
26
- <strong>Fast file‑upload malware scanning for Node.js</strong> — optional <strong>YARA</strong> integration, ZIP deep‑inspection, and drop‑in adapters for <em>Express</em>, <em>Koa</em>, and <em>Next.js</em>. Private by design. Typed. Tiny.
60
+ <p align="center">
61
+ <em>Scan files before they hit disk. Keep user data private. Ship with confidence.</em>
27
62
  </p>
28
63
 
29
64
  **Keywords:** file upload security · malware detection · YARA · Node.js middleware · Express · Koa · Next.js · ZIP bomb protection
30
65
 
31
-
66
+ ---
32
67
 
33
68
  <p align="center">
34
69
  <a href="https://www.npmjs.com/package/pompelmi"><img alt="npm version" src="https://img.shields.io/npm/v/pompelmi?label=version&color=0a7ea4&logo=npm"></a>
@@ -39,6 +74,13 @@
39
74
  <a href="https://snyk.io/test/github/pompelmi/pompelmi"><img alt="Known Vulnerabilities" src="https://snyk.io/test/github/pompelmi/pompelmi/badge.svg"></a>
40
75
  </p>
41
76
 
77
+ <p align="center">
78
+ <a href="https://www.npmjs.com/package/@pompelmi/cli"><img alt="CLI version" src="https://img.shields.io/npm/v/@pompelmi/cli?label=CLI&color=0a7ea4&logo=npm"></a>
79
+ <a href="https://www.npmjs.com/package/@pompelmi/nestjs-integration"><img alt="NestJS version" src="https://img.shields.io/npm/v/@pompelmi/nestjs-integration?label=NestJS&color=E0234E&logo=nestjs"></a>
80
+ <a href="https://www.npmjs.com/package/@pompelmi/express-middleware"><img alt="Express version" src="https://img.shields.io/npm/v/@pompelmi/express-middleware?label=Express&color=000000&logo=express"></a>
81
+ <a href="https://www.npmjs.com/package/@pompelmi/next-upload"><img alt="Next.js version" src="https://img.shields.io/npm/v/@pompelmi/next-upload?label=Next.js&color=000000&logo=nextdotjs"></a>
82
+ </p>
83
+
42
84
  <p align="center">
43
85
  <img alt="node" src="https://img.shields.io/badge/node-%3E%3D18-339933?logo=node.js&logoColor=white">
44
86
  <img alt="types" src="https://img.shields.io/badge/types-TypeScript-3178C6?logo=typescript&logoColor=white">
@@ -108,9 +150,12 @@
108
150
  - [Express](#express)
109
151
  - [Koa](#koa)
110
152
  - [Next.js (App Router)](#nextjs-app-router)
111
- - [CLI Tool](#cli-tool)
153
+ - [Adapters](#adapters)
154
+ - [GitHub Action](#github-action)
112
155
  - [Configuration](#configuration)
156
+ - [YARA Getting Started](#yara-getting-started)
113
157
  - [Security Notes](#security-notes)
158
+
114
159
  - [Testing & Development](#testing--development)
115
160
  - [FAQ](#faq)
116
161
  - [Contributing](#contributing)
@@ -118,6 +163,25 @@
118
163
 
119
164
  ---
120
165
 
166
+ ## 🌍 Translations
167
+
168
+ pompelmi documentation is available in multiple languages to help developers worldwide:
169
+
170
+ - 🇮🇹 **[Italiano (Italian)](docs/i18n/README.it.md)** — Documentazione completa in italiano
171
+ - 🇫🇷 **[Français (French)](docs/i18n/README.fr.md)** — Documentation complète en français
172
+ - 🇪🇸 **[Español (Spanish)](docs/i18n/README.es.md)** — Documentación completa en español
173
+ - 🇩🇪 **[Deutsch (German)](docs/i18n/README.de.md)** — Vollständige Dokumentation auf Deutsch
174
+ - 🇯🇵 **[日本語 (Japanese)](docs/i18n/README.ja.md)** — 日本語による完全なドキュメント
175
+ - 🇨🇳 **[简体中文 (Simplified Chinese)](docs/i18n/README.zh-CN.md)** — 完整的简体中文文档
176
+ - 🇰🇷 **[한국어 (Korean)](docs/i18n/README.ko.md)** — 완전한 한국어 문서
177
+ - 🇧🇷 **[Português (Brasil)](docs/i18n/README.pt-BR.md)** — Documentação completa em português
178
+ - 🇷🇺 **[Русский (Russian)](docs/i18n/README.ru.md)** — Полная документация на русском
179
+ - 🇹🇷 **[Türkçe (Turkish)](docs/i18n/README.tr.md)** — Türkçe tam dokümantasyon
180
+
181
+ **Help improve translations:** We welcome contributions to improve and maintain translations. The English README is the authoritative source. To contribute, please open a Pull Request with your improvements.
182
+
183
+ ---
184
+
121
185
  ## 🚀 Overview
122
186
 
123
187
  **pompelmi** scans untrusted file uploads **before** they hit disk. A tiny, TypeScript-first toolkit for Node.js with composable scanners, deep ZIP inspection, and optional signature engines.
@@ -130,7 +194,13 @@
130
194
 
131
195
  **📦 ZIP hardening** — traversal/bomb guards, polyglot & macro hints
132
196
 
133
- **🔌 Drop-in adapters** — Express, Koa, Fastify, Next.js
197
+ **🔌 Drop-in adapters** — Express, Koa, Fastify, Next.js, **NestJS**
198
+
199
+ **🌊 Stream-based scanning** — memory-efficient processing with configurable buffer limits
200
+
201
+ **⚙️ CLI for CI/CD** — standalone command-line tool for scanning files and directories
202
+
203
+ **🔍 Polyglot detection** — advanced magic bytes analysis and embedded script detection
134
204
 
135
205
  **📘 Typed & tiny** — modern TS, minimal surface, tree-shakeable
136
206
 
@@ -144,8 +214,16 @@
144
214
 
145
215
  **🔍 Built‑in scanners** — drop‑in **CommonHeuristicsScanner** (PDF risky actions, Office macros, PE header) and **Zip‑bomb Guard**; add your own or YARA via a tiny `{ scan(bytes) }` contract.
146
216
 
217
+ **🔬 Polyglot & embedded script detection** — advanced magic bytes analysis detects mixed-format files and embedded scripts with **30+ file signatures**.
218
+
219
+ **🌊 Memory-efficient streaming** — scan large files without loading them entirely into memory with automatic stream routing.
220
+
147
221
  **⚙️ Compose scanning** — run multiple scanners in parallel or sequentially with timeouts and short‑circuiting via `composeScanners()`.
148
222
 
223
+ **🏗️ Framework integrations** — native modules for **NestJS**, Express, Koa, Next.js, and Fastify with first-class TypeScript support.
224
+
225
+ **🔧 Production-ready CLI** — standalone tool for CI/CD pipelines with watch mode, multiple output formats (JSON, table, minimal).
226
+
149
227
  **☁️ Zero cloud** — scans run in‑process. Keep bytes private. Perfect for GDPR/HIPAA compliance.
150
228
 
151
229
  **👨‍💻 DX first** — TypeScript types, ESM/CJS builds, tiny API, adapters for popular web frameworks.
@@ -181,7 +259,6 @@
181
259
  \* You can run YARA alongside ClamAV, but it’s not built‑in.
182
260
 
183
261
  ---
184
-
185
262
  ## 💬 What Developers Say
186
263
 
187
264
  > "pompelmi made it incredibly easy to add malware scanning to our Express API. The TypeScript support is fantastic!"
@@ -233,10 +310,6 @@ Validate customer document uploads (ID verification, tax forms) without exposing
233
310
 
234
311
  Protect learning management systems from malicious file uploads while maintaining student privacy.
235
312
 
236
- ### 📱 SaaS Applications
237
-
238
- Add secure file upload capabilities to your multi-tenant platform with per-tenant policy customization.
239
-
240
313
  ### 🏢 Enterprise Document Management
241
314
 
242
315
  Scan files at ingestion time for corporate file sharing platforms, wikis, and collaboration tools.
@@ -249,6 +322,13 @@ Validate user-generated content uploads (images, videos, documents) before proce
249
322
 
250
323
  ## 🔧 Installation
251
324
 
325
+ **pompelmi** is a privacy-first Node.js library for local file scanning.
326
+
327
+ **Requirements:**
328
+ - Node.js 18+
329
+ - Optional: ClamAV binaries (for signature-based scanning)
330
+ - Optional: YARA libraries (for custom rules)
331
+
252
332
  <table>
253
333
  <tr>
254
334
  <td><b>npm</b></td>
@@ -268,7 +348,7 @@ Validate user-generated content uploads (images, videos, documents) before proce
268
348
  </tr>
269
349
  </table>
270
350
 
271
- ### 📦 Optional Framework Adapters
351
+ #### 📦 Optional Framework Adapters
272
352
 
273
353
  ```bash
274
354
  # Express
@@ -280,8 +360,14 @@ npm i @pompelmi/koa-middleware
280
360
  # Next.js
281
361
  npm i @pompelmi/next-upload
282
362
 
363
+ # NestJS
364
+ npm i @pompelmi/nestjs-integration
365
+
283
366
  # Fastify (alpha)
284
367
  npm i @pompelmi/fastify-plugin
368
+
369
+ # Standalone CLI
370
+ npm i -g @pompelmi/cli
285
371
  ```
286
372
 
287
373
  > **Note:** Core library works standalone. Install adapters only if using specific frameworks.
@@ -389,75 +475,66 @@ export const dynamic = 'force-dynamic';
389
475
  export const POST = createNextUploadHandler({ ...policy, scanner });
390
476
  ```
391
477
 
392
- ---
393
-
394
- ## 🖥️ CLI Tool
395
-
396
- **pompelmi** includes a modern command-line interface for scanning files directly from your terminal. Perfect for CI/CD pipelines, security audits, and local development.
397
-
398
- ### Installation
399
-
400
- ```bash
401
- # Install globally
402
- npm install -g @pompelmi/cli
478
+ ### NestJS
403
479
 
404
- # Or use with npx
405
- npx @pompelmi/cli scan file.pdf
480
+ ```ts
481
+ // app.module.ts
482
+ import { Module } from '@nestjs/common';
483
+ import { PompelmiModule } from '@pompelmi/nestjs-integration';
484
+ import { CommonHeuristicsScanner } from 'pompelmi';
485
+
486
+ @Module({
487
+ imports: [
488
+ PompelmiModule.forRoot({
489
+ includeExtensions: ['pdf', 'zip', 'png', 'jpg'],
490
+ allowedMimeTypes: ['application/pdf', 'application/zip', 'image/png', 'image/jpeg'],
491
+ maxFileSizeBytes: 10 * 1024 * 1024,
492
+ scanners: [CommonHeuristicsScanner],
493
+ }),
494
+ ],
495
+ })
496
+ export class AppModule {}
497
+
498
+ // upload.controller.ts
499
+ import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
500
+ import { FileInterceptor } from '@nestjs/platform-express';
501
+ import { PompelmiInterceptor, PompelmiResult } from '@pompelmi/nestjs-integration';
502
+
503
+ @Controller('upload')
504
+ export class UploadController {
505
+ @Post()
506
+ @UseInterceptors(FileInterceptor('file'), PompelmiInterceptor)
507
+ async uploadFile(@UploadedFile() file: Express.Multer.File & { pompelmi?: PompelmiResult }) {
508
+ return {
509
+ success: true,
510
+ verdict: file.pompelmi?.verdict
511
+ };
512
+ }
513
+ }
406
514
  ```
407
515
 
408
- ### Features
516
+ > See `packages/nestjs-integration/README.md` for full documentation.
409
517
 
410
- 🎨 **Modern Terminal UI** — Emoji-rich interface with progress indicators
411
- ⚡ **Fast Scanning** — Parallel file processing with real-time feedback
412
- 📊 **Detailed Reports** — Human-readable scan summaries with timing
413
- 🎯 **Smart Detection** — Built-in heuristics for common threats
414
- 🛡️ **Safe Defaults** — ZIP bomb protection and file size limits
415
-
416
- ### Usage
518
+ ### CLI Usage
417
519
 
418
520
  ```bash
419
521
  # Scan a single file
420
- pompelmi scan document.pdf
522
+ pompelmi scan file.pdf
421
523
 
422
- # Scan a directory with progress
423
- pompelmi scan-dir ./uploads
524
+ # Scan directory recursively
525
+ pompelmi scan ./uploads --recursive
424
526
 
425
527
  # Watch directory for changes
426
528
  pompelmi watch ./uploads
427
529
 
428
- # Get help
429
- pompelmi --help
430
- ```
431
-
432
- ### Example Output
433
-
434
- ```
435
- 🛡️ Pompelmi Security Scanner v0.23.0
436
-
437
- 📁 Scanning: document.pdf
438
- 🔍 Checking file safety...
439
- ✅ File passed all security checks
530
+ # JSON output for CI/CD
531
+ pompelmi scan ./dist --output json --exit-on-suspicious
440
532
 
441
- 📊 Scan Summary (0.1s)
442
- Files scanned: 1
443
- • Clean: 1 ✅
444
- • Suspicious: 0 ⚠️
445
- • Malicious: 0 ❌
533
+ # Full options
534
+ pompelmi scan --help
446
535
  ```
447
536
 
448
- ### CI/CD Integration
449
-
450
- Use the CLI in your build pipelines:
451
-
452
- ```yaml
453
- # GitHub Actions
454
- - name: Security Scan
455
- run: npx @pompelmi/cli scan-dir ./dist
456
-
457
- # GitLab CI
458
- script:
459
- - npx @pompelmi/cli scan build.zip
460
- ```
537
+ > See `packages/cli/README.md` for comprehensive CLI documentation.
461
538
 
462
539
  ---
463
540
 
@@ -858,9 +935,7 @@ You should see an HTTP **422 Unprocessable Entity** (blocked by policy). Clean f
858
935
 
859
936
  ---
860
937
 
861
- [...]
862
-
863
- ## 🔔 Releases & security
938
+ ## Releases & security
864
939
 
865
940
  - **Changelog / releases:** see [GitHub Releases](https://github.com/pompelmi/pompelmi/releases).
866
941
  - **Security disclosures:** please use [GitHub Security Advisories](https://github.com/pompelmi/pompelmi/security/advisories). We’ll coordinate a fix before public disclosure.
package/dist/pompelmi.cjs CHANGED
@@ -54,9 +54,10 @@ function createPresetScanner(preset, opts = {}) {
54
54
  opts.decompilationDepth || 'basic';
55
55
  if (!opts.decompilationEngine || opts.decompilationEngine === 'binaryninja-hlil' || opts.decompilationEngine === 'both') {
56
56
  try {
57
- // Dynamic import to avoid bundling issues
58
- import('@pompelmi/engine-binaryninja').then(({ createBinaryNinjaScanner }) => {
59
- const binjaScanner = createBinaryNinjaScanner({
57
+ // Dynamic import to avoid bundling issues - using Function to bypass TypeScript type checking
58
+ const importModule = new Function('specifier', 'return import(specifier)');
59
+ importModule('@pompelmi/engine-binaryninja').then((mod) => {
60
+ const binjaScanner = mod.createBinaryNinjaScanner({
60
61
  timeout: opts.decompilationTimeout || opts.timeout || 30000,
61
62
  depth,
62
63
  pythonPath: opts.pythonPath,
@@ -73,9 +74,10 @@ function createPresetScanner(preset, opts = {}) {
73
74
  }
74
75
  if (!opts.decompilationEngine || opts.decompilationEngine === 'ghidra-pcode' || opts.decompilationEngine === 'both') {
75
76
  try {
76
- // Dynamic import for Ghidra engine (when implemented)
77
- import('@pompelmi/engine-ghidra').then(({ createGhidraScanner }) => {
78
- const ghidraScanner = createGhidraScanner({
77
+ // Dynamic import for Ghidra engine (when implemented) - using Function to bypass TypeScript type checking
78
+ const importModule = new Function('specifier', 'return import(specifier)');
79
+ importModule('@pompelmi/engine-ghidra').then((mod) => {
80
+ const ghidraScanner = mod.createGhidraScanner({
79
81
  timeout: opts.decompilationTimeout || opts.timeout || 30000,
80
82
  depth,
81
83
  ghidraPath: opts.ghidraPath,
@@ -2272,13 +2274,13 @@ class HipaaComplianceManager {
2272
2274
  constructor(config) {
2273
2275
  this.auditEvents = [];
2274
2276
  this.config = {
2275
- enabled: true,
2276
2277
  sanitizeErrors: true,
2277
2278
  sanitizeFilenames: true,
2278
2279
  encryptTempFiles: true,
2279
2280
  memoryProtection: true,
2280
2281
  requireSecureTransport: true,
2281
- ...config
2282
+ ...config,
2283
+ enabled: config.enabled !== undefined ? config.enabled : true
2282
2284
  };
2283
2285
  this.sessionId = this.generateSessionId();
2284
2286
  }