pompelmi 0.22.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,8 +150,12 @@
108
150
  - [Express](#express)
109
151
  - [Koa](#koa)
110
152
  - [Next.js (App Router)](#nextjs-app-router)
153
+ - [Adapters](#adapters)
154
+ - [GitHub Action](#github-action)
111
155
  - [Configuration](#configuration)
156
+ - [YARA Getting Started](#yara-getting-started)
112
157
  - [Security Notes](#security-notes)
158
+
113
159
  - [Testing & Development](#testing--development)
114
160
  - [FAQ](#faq)
115
161
  - [Contributing](#contributing)
@@ -117,6 +163,25 @@
117
163
 
118
164
  ---
119
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
+
120
185
  ## 🚀 Overview
121
186
 
122
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.
@@ -129,7 +194,13 @@
129
194
 
130
195
  **📦 ZIP hardening** — traversal/bomb guards, polyglot & macro hints
131
196
 
132
- **🔌 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
133
204
 
134
205
  **📘 Typed & tiny** — modern TS, minimal surface, tree-shakeable
135
206
 
@@ -143,8 +214,16 @@
143
214
 
144
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.
145
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
+
146
221
  **⚙️ Compose scanning** — run multiple scanners in parallel or sequentially with timeouts and short‑circuiting via `composeScanners()`.
147
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
+
148
227
  **☁️ Zero cloud** — scans run in‑process. Keep bytes private. Perfect for GDPR/HIPAA compliance.
149
228
 
150
229
  **👨‍💻 DX first** — TypeScript types, ESM/CJS builds, tiny API, adapters for popular web frameworks.
@@ -180,7 +259,6 @@
180
259
  \* You can run YARA alongside ClamAV, but it’s not built‑in.
181
260
 
182
261
  ---
183
-
184
262
  ## 💬 What Developers Say
185
263
 
186
264
  > "pompelmi made it incredibly easy to add malware scanning to our Express API. The TypeScript support is fantastic!"
@@ -232,10 +310,6 @@ Validate customer document uploads (ID verification, tax forms) without exposing
232
310
 
233
311
  Protect learning management systems from malicious file uploads while maintaining student privacy.
234
312
 
235
- ### 📱 SaaS Applications
236
-
237
- Add secure file upload capabilities to your multi-tenant platform with per-tenant policy customization.
238
-
239
313
  ### 🏢 Enterprise Document Management
240
314
 
241
315
  Scan files at ingestion time for corporate file sharing platforms, wikis, and collaboration tools.
@@ -248,6 +322,13 @@ Validate user-generated content uploads (images, videos, documents) before proce
248
322
 
249
323
  ## 🔧 Installation
250
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
+
251
332
  <table>
252
333
  <tr>
253
334
  <td><b>npm</b></td>
@@ -267,7 +348,7 @@ Validate user-generated content uploads (images, videos, documents) before proce
267
348
  </tr>
268
349
  </table>
269
350
 
270
- ### 📦 Optional Framework Adapters
351
+ #### 📦 Optional Framework Adapters
271
352
 
272
353
  ```bash
273
354
  # Express
@@ -279,8 +360,14 @@ npm i @pompelmi/koa-middleware
279
360
  # Next.js
280
361
  npm i @pompelmi/next-upload
281
362
 
363
+ # NestJS
364
+ npm i @pompelmi/nestjs-integration
365
+
282
366
  # Fastify (alpha)
283
367
  npm i @pompelmi/fastify-plugin
368
+
369
+ # Standalone CLI
370
+ npm i -g @pompelmi/cli
284
371
  ```
285
372
 
286
373
  > **Note:** Core library works standalone. Install adapters only if using specific frameworks.
@@ -388,6 +475,67 @@ export const dynamic = 'force-dynamic';
388
475
  export const POST = createNextUploadHandler({ ...policy, scanner });
389
476
  ```
390
477
 
478
+ ### NestJS
479
+
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
+ }
514
+ ```
515
+
516
+ > See `packages/nestjs-integration/README.md` for full documentation.
517
+
518
+ ### CLI Usage
519
+
520
+ ```bash
521
+ # Scan a single file
522
+ pompelmi scan file.pdf
523
+
524
+ # Scan directory recursively
525
+ pompelmi scan ./uploads --recursive
526
+
527
+ # Watch directory for changes
528
+ pompelmi watch ./uploads
529
+
530
+ # JSON output for CI/CD
531
+ pompelmi scan ./dist --output json --exit-on-suspicious
532
+
533
+ # Full options
534
+ pompelmi scan --help
535
+ ```
536
+
537
+ > See `packages/cli/README.md` for comprehensive CLI documentation.
538
+
391
539
  ---
392
540
 
393
541
  ## 🤖 GitHub Action
@@ -787,9 +935,7 @@ You should see an HTTP **422 Unprocessable Entity** (blocked by policy). Clean f
787
935
 
788
936
  ---
789
937
 
790
- [...]
791
-
792
- ## 🔔 Releases & security
938
+ ## Releases & security
793
939
 
794
940
  - **Changelog / releases:** see [GitHub Releases](https://github.com/pompelmi/pompelmi/releases).
795
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
  }