pompelmi 0.35.1 → 0.35.3

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.
Files changed (2) hide show
  1. package/README.md +108 -114
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,162 +1,152 @@
1
1
  <div align="center">
2
- <img src="assets/logo.svg" alt="Pompelmi logo" width="160" />
3
- <h1>Pompelmi — in-process file upload security for Node.js</h1>
4
- <p>Scan and block risky uploads before storage — no cloud API, no daemon, no required data egress.</p>
2
+ <img src="./assets/logo.svg" alt="Pompelmi logo" width="144" />
3
+
4
+ <h1>Pompelmi</h1>
5
+
6
+ <p><strong>Route-level upload security for Node.js.</strong></p>
7
+
8
+ <p>Inspect untrusted uploads before storage.</p>
9
+
5
10
  <p>
6
- <a href="https://www.npmjs.com/package/pompelmi"><img alt="npm version" src="https://img.shields.io/npm/v/pompelmi"></a>
7
- <a href="https://github.com/pompelmi/pompelmi/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/pompelmi/pompelmi/ci.yml?label=ci"></a>
8
- <a href="https://codecov.io/gh/pompelmi/pompelmi"><img alt="Codecov" src="https://codecov.io/gh/pompelmi/pompelmi/branch/main/graph/badge.svg?flag=core"></a>
9
- <a href="https://github.com/pompelmi/pompelmi/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/pompelmi/pompelmi"></a>
10
- <a href="https://www.npmjs.com/package/pompelmi"><img alt="npm downloads" src="https://img.shields.io/npm/dm/pompelmi"></a>
11
+ MIME and extension spoofing · archive abuse · risky document and binary
12
+ signals · optional YARA
11
13
  </p>
14
+
15
+ <p><code>clean</code> · <code>suspicious</code> · <code>malicious</code></p>
16
+
12
17
  <p>
13
- <a href="https://github.com/sorrycc/awesome-javascript"><img alt="Mentioned in Awesome JavaScript" src="https://img.shields.io/badge/mentioned-Awesome%20JavaScript-f59e0b"></a>
14
- <a href="https://github.com/dzharii/awesome-typescript"><img alt="Mentioned in Awesome TypeScript" src="https://img.shields.io/badge/mentioned-Awesome%20TypeScript-3178C6"></a>
15
- <a href="https://nodeweekly.com/issues/594"><img alt="Featured in Node Weekly #594" src="https://img.shields.io/badge/featured-Node%20Weekly%20%23594-339933?logo=node.js&logoColor=white"></a>
16
- <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>
18
+ <sub>Express · Next.js · NestJS · Fastify · Koa · Nuxt/Nitro · S3 quarantine flows · CI/CD</sub>
17
19
  </p>
20
+
21
+ <p><sub>Open-source core · MIT · Node.js 18+</sub></p>
22
+
18
23
  <p>
19
- <a href="https://www.detectionengineering.net/p/det-eng-weekly-issue-124-the-defcon"><img alt="Featured in Detection Engineering Weekly #124" src="https://img.shields.io/badge/featured-Detection%20Engineering%20Weekly%20%23124-0A84FF?logo=substack&logoColor=white"></a>
20
- <a href="https://stackoverflow.blog/2026/02/23/defense-against-uploads-oss-file-scanner-pompelmi/"><img alt="Featured on Stack Overflow by Ryan Donovan" src="https://img.shields.io/badge/featured-Stack%20Overflow-F48024?logo=stackoverflow&logoColor=white"></a>
21
- <a href="https://stackoverflow.blog/newsletter/issue-319-dogfooding-your-sdlc/"><img alt="Featured in The Overflow #319" src="https://img.shields.io/badge/featured-The%20Overflow%20%23319-F48024?logo=stackoverflow&logoColor=white"></a>
22
- <a href="https://www.helpnetsecurity.com/2026/02/02/pompelmi-open-source-secure-file-upload-scanning-node-js/"><img alt="Featured in Help Net Security" src="https://img.shields.io/badge/featured-Help%20Net%20Security-2563eb"></a>
24
+ <a href="https://www.npmjs.com/package/pompelmi"><img alt="npm version" src="https://img.shields.io/npm/v/pompelmi" /></a>
25
+ <a href="https://github.com/pompelmi/pompelmi/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/pompelmi/pompelmi/ci.yml?label=ci" /></a>
26
+ <a href="https://codecov.io/gh/pompelmi/pompelmi"><img alt="codecov" src="https://codecov.io/gh/pompelmi/pompelmi/graph/badge.svg" /></a>
27
+ <a href="https://github.com/pompelmi/pompelmi/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/pompelmi/pompelmi?style=social" /></a>
28
+ <a href="https://www.npmjs.com/package/pompelmi"><img alt="npm weekly downloads" src="https://img.shields.io/npm/dw/pompelmi" /></a>
29
+ <a href="https://www.npmjs.com/package/pompelmi"><img alt="npm monthly downloads" src="https://img.shields.io/npm/dm/pompelmi" /></a>
23
30
  </p>
24
- </div>
25
31
 
26
- > **Why:** Upload endpoints are part of your attack surface. Pompelmi inspects untrusted files _before_ they hit storage or downstream processors.
27
- > **How:** in-process scanning + policy packs (MIME sniffing, archive abuse checks, risky structures) with optional YARA.
28
- > **Works with:** Express, Next.js, NestJS, Fastify, Koa (plus adapters in `packages/`).
32
+ <p>
33
+ <a href="https://pompelmi.github.io/pompelmi/getting-started/"><strong>Getting started</strong></a>
34
+ ·
35
+ <a href="https://pompelmi.github.io/pompelmi/#browser-preview"><strong>Browser preview</strong></a>
36
+ ·
37
+ <a href="./examples/demo"><strong>Express demo</strong></a>
38
+ ·
39
+ <a href="./examples/README.md"><strong>Examples</strong></a>
40
+ </p>
41
+ </div>
29
42
 
30
- ## Demo
43
+ <p align="center">
44
+ Mentioned by <a href="https://nodeweekly.com/issues/594">Node Weekly</a>,
45
+ <a href="https://stackoverflow.blog/2026/02/23/defense-against-uploads-oss-file-scanner-pompelmi/">Stack Overflow</a>,
46
+ <a href="https://www.helpnetsecurity.com/2026/02/02/pompelmi-open-source-secure-file-upload-scanning-node-js/">Help Net Security</a>,
47
+ <a href="https://github.com/sorrycc/awesome-javascript">Awesome JavaScript</a>,
48
+ and
49
+ <a href="https://github.com/dzharii/awesome-typescript">Awesome TypeScript</a>.
50
+ </p>
31
51
 
32
- ![Pompelmi demo](assets/malware-detection-node-demo.gif)
52
+ ## Quick Start
33
53
 
34
- ## Install
54
+ Install the core package:
35
55
 
36
56
  ```bash
37
57
  npm install pompelmi
38
58
  ```
39
59
 
40
- Requires Node.js 18+.
60
+ Minimal route-level example:
41
61
 
42
- ## Try in 5 minutes
62
+ ```ts
63
+ import { scanBytes, STRICT_PUBLIC_UPLOAD } from 'pompelmi';
43
64
 
44
- 1. Install:
65
+ const report = await scanBytes(req.file.buffer, {
66
+ filename: req.file.originalname,
67
+ mimeType: req.file.mimetype,
68
+ policy: STRICT_PUBLIC_UPLOAD,
69
+ failClosed: true,
70
+ });
45
71
 
46
- ```bash
47
- npm install pompelmi
72
+ if (report.verdict !== 'clean') {
73
+ return res.status(422).json({
74
+ error: 'Upload blocked',
75
+ verdict: report.verdict,
76
+ reasons: report.reasons,
77
+ });
78
+ }
79
+
80
+ return res.status(200).json({ verdict: report.verdict });
48
81
  ```
49
82
 
50
- 2. Create `scan-test.mjs`:
83
+ Start with [Getting started](https://pompelmi.github.io/pompelmi/getting-started/) for a local scan in under a minute, open the [browser preview](https://pompelmi.github.io/pompelmi/#browser-preview) to inspect the verdict flow without sending files anywhere, or run the minimal [Express demo](./examples/demo).
51
84
 
52
- ```js
53
- import { scanBytes } from "pompelmi";
54
- import { readFileSync } from "node:fs";
85
+ If Pompelmi matches how you want upload security to work, star the repo so more Node.js teams can find it.
55
86
 
56
- const buffer = readFileSync("./package.json");
87
+ ## Why It Exists
57
88
 
58
- const report = await scanBytes(buffer, {
59
- filename: "package.json",
60
- mimeType: "application/json",
61
- });
89
+ Upload endpoints are part of your attack surface. A file can look harmless at the form layer and become dangerous only after storage, extraction, rendering, or downstream parsing.
62
90
 
63
- console.log("Verdict:", report.verdict);
64
- console.log("Reasons:", report.reasons);
65
- console.log("Duration:", report.durationMs, "ms");
66
- ```
91
+ Pompelmi keeps the first decision inside the application path, where the route still knows the file class, trust level, storage path, and failure mode.
67
92
 
68
- 3. Run it:
93
+ ## What It Checks
69
94
 
70
- ```bash
71
- node scan-test.mjs
72
- ```
95
+ - MIME sniffing, magic-byte validation, and extension allowlists
96
+ - risky archive structures such as traversal, deep nesting, entry-count abuse, and ZIP bomb-style expansion
97
+ - suspicious document and binary signals such as risky PDF actions, Office macro hints, PE headers, and polyglot files
98
+ - optional YARA or other scanner matches
99
+ - route-level verdicts that support reject, quarantine, or promote workflows
73
100
 
74
- Next: see the demo under [examples/demo](./examples/demo) (upload route) or the docs [Getting started](https://pompelmi.github.io/pompelmi/getting-started/) guide.
101
+ ## Where It Fits
75
102
 
76
- ## Quick Start
103
+ - public or semi-trusted upload endpoints that should inspect first and store later
104
+ - memory-backed multipart routes in Express, Next.js, NestJS, Fastify, and Koa
105
+ - quarantine and promotion workflows for S3 or other object storage
106
+ - document, image, and archive routes that need different policies
107
+ - CI/CD or internal artifact scanning before promotion
77
108
 
78
- ```ts
79
- import { scanBytes, STRICT_PUBLIC_UPLOAD } from "pompelmi";
109
+ ## Why Not Just X?
80
110
 
81
- const report = await scanBytes(file.buffer, {
82
- filename: file.originalname,
83
- mimeType: file.mimetype,
84
- policy: STRICT_PUBLIC_UPLOAD,
85
- failClosed: true,
86
- });
87
-
88
- if (report.verdict !== "clean") {
89
- return res.status(422).json({
90
- error: "Upload blocked",
91
- verdict: report.verdict,
92
- reasons: report.reasons,
93
- });
94
- }
95
- ```
111
+ | Approach | Useful for | What it misses |
112
+ | --- | --- | --- |
113
+ | Browser MIME and extension checks | Fast client-side hints and UX feedback | Filenames and client-reported MIME are easy to spoof |
114
+ | Simple file-type or magic-byte checks | Confirming the file appears to be the claimed type | Risky internal structure, archive abuse, and route policy decisions |
115
+ | Antivirus-only thinking | Known malicious matches and signature-based detection | Route context, spoofing checks, storage decisions, and non-signature risk signals |
116
+ | Pompelmi at the upload route | Inspect-first, store-later decisions with policy, structure checks, and optional YARA | It is not a full antivirus replacement on its own |
96
117
 
97
- ## Start Here
118
+ ## Integrations
98
119
 
99
- - Express: [Docs](https://pompelmi.github.io/pompelmi/how-to/express/) · [Examples](./examples/express-minimal)
100
- - Next.js: [Docs](https://pompelmi.github.io/pompelmi/how-to/nextjs/) · [Examples](./examples/next-app-router)
120
+ - Express: [Docs](https://pompelmi.github.io/pompelmi/how-to/express/) · [Minimal example](./examples/express-minimal) · [Demo](./examples/demo)
121
+ - Next.js: [Docs](https://pompelmi.github.io/pompelmi/how-to/nextjs/) · [Example](./examples/next-app-router)
101
122
  - NestJS: [Docs](https://pompelmi.github.io/pompelmi/how-to/nestjs/) · [Example app](./examples/nestjs-app)
102
123
  - Fastify: [Docs](https://pompelmi.github.io/pompelmi/how-to/fastify/) · [Package](./packages/fastify-plugin)
103
124
  - Koa: [Docs](https://pompelmi.github.io/pompelmi/how-to/koa/) · [Package](./packages/koa-middleware)
104
- - CI/CD: [Use case](https://pompelmi.github.io/pompelmi/use-cases/cicd-artifact-scanning/) · [Blog](https://pompelmi.github.io/pompelmi/blog/cicd-scan-build-artifacts/)
125
+ - Nuxt/Nitro: [Docs](https://pompelmi.github.io/pompelmi/how-to/nuxt-nitro/)
105
126
  - S3 / object storage: [Tutorial](https://pompelmi.github.io/pompelmi/tutorials/secure-s3-presigned-uploads-with-malware-scanning/) · [Use case](https://pompelmi.github.io/pompelmi/use-cases/s3-presigned-upload-security/)
127
+ - CI/CD: [Use case](https://pompelmi.github.io/pompelmi/use-cases/cicd-artifact-scanning/) · [Blog](https://pompelmi.github.io/pompelmi/blog/cicd-scan-build-artifacts/)
128
+
129
+ ## Demo, Preview, and Examples
106
130
 
107
- ## Go Deeper
131
+ ![Pompelmi upload security demo](assets/malware-detection-node-demo.gif)
132
+
133
+ - [Browser preview](https://pompelmi.github.io/pompelmi/#browser-preview) for a fast local evaluation of the verdict UX
134
+ - [Demo](./examples/demo) for a tiny Express upload gate that returns `clean`, `suspicious`, or `malicious` before storage
135
+ - [Examples index](./examples/README.md) for framework-specific and production-oriented examples
136
+
137
+ ## Docs
108
138
 
109
139
  - [Docs home](https://pompelmi.github.io/pompelmi/)
140
+ - [Getting started](https://pompelmi.github.io/pompelmi/getting-started/)
110
141
  - [Use cases](https://pompelmi.github.io/pompelmi/use-cases/)
111
142
  - [Comparisons](https://pompelmi.github.io/pompelmi/comparisons/)
112
143
  - [Tutorials](https://pompelmi.github.io/pompelmi/tutorials/)
113
144
  - [Featured in](https://pompelmi.github.io/pompelmi/featured-in/)
114
145
  - [Translations](https://pompelmi.github.io/pompelmi/translations/)
115
- - [Examples index](./examples/README.md)
116
- - [Demo example](./examples/demo)
117
- - [Contributing](./CONTRIBUTING.md)
118
- - [Security](./SECURITY.md)
119
- - [Roadmap](./ROADMAP.md)
120
-
121
- ## What It Checks
122
-
123
- Upload endpoints are part of your attack surface. A renamed executable, a risky PDF, or a hostile archive can look harmless until it is stored, unpacked, served, or parsed by another system.
124
-
125
- Pompelmi adds checks at the upload boundary for:
126
-
127
- - MIME spoofing and magic-byte mismatches
128
- - Archive abuse such as ZIP bombs, traversal, and deep nesting
129
- - Polyglot files and risky document structures
130
- - Optional YARA-based signature matching
131
-
132
- The goal is simple: inspect first, store later.
133
-
134
- ## Ecosystem
135
146
 
136
- - `pompelmi`
137
- - `@pompelmi/express-middleware`
138
- - `@pompelmi/koa-middleware`
139
- - `@pompelmi/next-upload`
140
- - `@pompelmi/nestjs-integration`
141
- - `@pompelmi/fastify-plugin`
142
- - `@pompelmi/ui-react`
143
- - `@pompelmi/cli`
147
+ ## Enterprise and Commercial Support
144
148
 
145
- ## Repository Layout
146
-
147
- - `src/` core library
148
- - `packages/` framework adapters and supporting packages
149
- - `examples/` runnable examples
150
- - `tests/` test coverage
151
- - `website/` public docs, blog, and discovery site
152
-
153
- ## Development
154
-
155
- ```bash
156
- pnpm install
157
- pnpm test
158
- pnpm build
159
- ```
149
+ The MIT core remains the primary path. Teams that need private rollout help, architecture review, or policy tuning can use the existing [enterprise support path](https://pompelmi.github.io/pompelmi/enterprise/).
160
150
 
161
151
  <!-- MENTIONS:START -->
162
152
 
@@ -189,6 +179,10 @@ Full page: [pompelmi.github.io/pompelmi/featured-in](https://pompelmi.github.io/
189
179
 
190
180
  <!-- MENTIONS:END -->
191
181
 
192
- ## License
182
+ ## Project
193
183
 
194
- [MIT](./LICENSE)
184
+ - [Contributing](./CONTRIBUTING.md)
185
+ - [Security](./SECURITY.md)
186
+ - [Roadmap](./ROADMAP.md)
187
+ - [GitHub Discussions](https://github.com/pompelmi/pompelmi/discussions)
188
+ - [License](./LICENSE)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pompelmi",
3
- "version": "0.35.1",
4
- "description": "Secure file uploads for Node.js. Scan untrusted files before storage with in-process, local-first checks for MIME spoofing, archive bombs, risky document structures, and optional YARA.",
3
+ "version": "0.35.3",
4
+ "description": "Inspect untrusted uploads before storage in Node.js. Open-source upload security with checks for spoofing, archive abuse, risky document and binary signals, and optional YARA.",
5
5
  "main": "./dist/pompelmi.cjs",
6
6
  "module": "./dist/pompelmi.esm.js",
7
7
  "type": "module",