chain-audit 0.5.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Hubert Kasperek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,460 @@
1
+ # chain-audit
2
+
3
+ [![CI](https://github.com/hukasx0/chain-audit/actions/workflows/ci.yml/badge.svg)](https://github.com/hukasx0/chain-audit/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/chain-audit.svg)](https://www.npmjs.com/package/chain-audit)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![Node.js Version](https://img.shields.io/node/v/chain-audit.svg)](https://nodejs.org)
7
+
8
+ **Fast, zero-dependency CLI to detect supply chain attacks in `node_modules`.**
9
+
10
+ 📖 **[Documentation](https://github.com/hukasx0/chain-audit)** • 🐛 **[Report Bug](https://github.com/hukasx0/chain-audit/issues)** • 💡 **[Request Feature](https://github.com/hukasx0/chain-audit/issues)** • 📦 **[npm package](https://www.npmjs.com/package/chain-audit)**
11
+
12
+ > ⚠️ Supply chain attacks are on the rise. Incidents like [event-stream](https://blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident), [ua-parser-js](https://github.com/advisories/GHSA-pjwm-rvh2-c87w), [node-ipc](https://snyk.io/blog/peacenotwar-malicious-npm-node-ipc-package-vulnerability/), and [Shai-Hulud 2.0](https://www.wiz.io/blog/shai-hulud-2-0-aftermath-ongoing-supply-chain-attack) (November 2025 – compromised PostHog, Postman, AsyncAPI and leaked thousands of secrets) have shown that even popular packages can be compromised. **`npm audit` only detects known CVEs** – it won't catch a malicious postinstall script added yesterday.
13
+
14
+ **chain-audit** fills this gap by scanning for suspicious patterns that indicate an active attack, not just known vulnerabilities.
15
+
16
+ ---
17
+
18
+ Scans your installed dependencies for malicious patterns including:
19
+ - 🔴 Extraneous packages not in lockfile
20
+ - 🔴 Version mismatches vs lockfile
21
+ - 🔴 Malicious install scripts (preinstall, postinstall, etc.)
22
+ - 🔴 Network access patterns (curl, wget, fetch, Node.js http/https)
23
+ - 🔴 Typosquatting attempts
24
+ - 🔴 Obfuscated code (base64, hex encoding)
25
+ - 🔴 Credential/secret stealing patterns (env vars + network)
26
+ - 🟡 Native binary modules
27
+ - 🟡 Dynamic code execution (eval, Function, child_process)
28
+
29
+ ## Why chain-audit?
30
+
31
+ | Feature | chain-audit | npm audit |
32
+ |---------|-------------|-----------|
33
+ | Detects known CVEs | ❌ | ✅ |
34
+ | Detects malicious install scripts | ✅ | ❌ |
35
+ | Detects typosquatting | ✅ | ❌ |
36
+ | Detects extraneous packages | ✅ | ❌ |
37
+ | Detects obfuscated code | ✅ | ❌ |
38
+ | Zero dependencies | ✅ | N/A |
39
+ | Works offline | ✅ | ❌ |
40
+ | SARIF output (GitHub integration) | ✅ | ❌ |
41
+
42
+ **Use both together** – `npm audit` for known vulnerabilities, `chain-audit` for detecting novel attacks.
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ # Global install
48
+ npm install -g chain-audit
49
+
50
+ # Or use directly with npx
51
+ npx chain-audit
52
+
53
+ # Or as dev dependency
54
+ npm install -D chain-audit
55
+
56
+ # Or with bun
57
+ bun add -d chain-audit
58
+ ```
59
+
60
+ ### Single Executable (Standalone Binary)
61
+
62
+ You can compile chain-audit to a standalone binary using Bun:
63
+
64
+ ```bash
65
+ # Clone the repository
66
+ git clone https://github.com/hukasx0/chain-audit.git
67
+ cd chain-audit
68
+
69
+ # Compile to single executable
70
+ bun build src/index.js --compile --outfile chain-audit
71
+
72
+ # Now you have a standalone binary
73
+ ./chain-audit --help
74
+ ```
75
+
76
+ This creates a self-contained executable that doesn't require Node.js or Bun to be installed. Perfect for:
77
+ - CI/CD environments without Node.js
78
+ - Air-gapped systems
79
+ - Distribution to teams without package managers
80
+
81
+ ## Quick Start
82
+
83
+ ```bash
84
+ # Scan current project
85
+ chain-audit
86
+
87
+ # Fail CI on high severity issues
88
+ chain-audit --fail-on high
89
+
90
+ # JSON output for processing
91
+ chain-audit --json
92
+
93
+ # SARIF output for GitHub Code Scanning
94
+ chain-audit --sarif > results.sarif
95
+
96
+ # Deep code analysis (slower but more thorough)
97
+ chain-audit --scan-code
98
+ ```
99
+
100
+ ## CLI Options
101
+
102
+ | Option | Description |
103
+ |--------|-------------|
104
+ | `-n, --node-modules <path>` | Path to node_modules (default: `./node_modules`) |
105
+ | `-l, --lock <path>` | Path to lockfile (auto-detects npm, yarn, pnpm, bun) |
106
+ | `-c, --config <path>` | Path to config file |
107
+ | `--json` | Output as JSON |
108
+ | `--sarif` | Output as SARIF (for GitHub Code Scanning) |
109
+ | `--fail-on <level>` | Exit 1 if max severity >= level |
110
+ | `--scan-code` | Deep scan JS files for suspicious patterns |
111
+ | `-q, --quiet` | Suppress warnings |
112
+ | `-v, --version` | Print version |
113
+ | `-h, --help` | Show help |
114
+
115
+ ## Severity Levels
116
+
117
+ | Level | Description | Example |
118
+ |-------|-------------|---------|
119
+ | `critical` | Highly likely malicious | Obfuscated code with network access, extraneous packages |
120
+ | `high` | Strong attack indicators | Suspicious install scripts with network/exec, typosquatting |
121
+ | `medium` | Warrants investigation | Install scripts, shell execution patterns |
122
+ | `low` | Informational | Native binaries, minimal metadata |
123
+ | `info` | Metadata only | Trusted packages with install scripts |
124
+
125
+ ## Example Output
126
+
127
+ ```
128
+ chain-audit v0.5.0
129
+ ────────────────────────────────────────────────────────────
130
+
131
+ node_modules: /path/to/project/node_modules
132
+ lockfile: /path/to/project/package-lock.json
133
+ lockfile type: npm-v2
134
+ packages scanned: 847
135
+
136
+ Found 3 potential issue(s):
137
+
138
+ ── CRITICAL ──
139
+ ● evil-package@1.0.0
140
+ reason: extraneous_package
141
+ detail: Package exists in node_modules but is missing from lockfile
142
+ fix: Run `npm ci` to reinstall from lockfile
143
+
144
+ ── HIGH ──
145
+ ● suspic-lib@2.0.0
146
+ reason: network_access_script
147
+ detail: Script "postinstall" contains network access pattern: curl https://...
148
+ fix: Verify that network access is legitimate
149
+
150
+ ── MEDIUM ──
151
+ ● some-addon@1.2.3
152
+ reason: install_script
153
+ detail: Has postinstall script: node-gyp rebuild
154
+ fix: Review the script to ensure it performs only expected operations
155
+
156
+ ────────────────────────────────────────────────────────────
157
+ Summary:
158
+ info: 0 │ low: 0 │ medium: 1 │ high: 1 │ critical: 1
159
+
160
+ Max severity: CRITICAL
161
+ ```
162
+
163
+ ## Configuration
164
+
165
+ Create `.chainauditrc.json` in your project root:
166
+
167
+ ```json
168
+ {
169
+ "ignoredPackages": [
170
+ "@types/*",
171
+ "my-internal-*"
172
+ ],
173
+ "ignoredRules": [
174
+ "native_binary"
175
+ ],
176
+ "trustedPackages": [
177
+ "esbuild",
178
+ "@swc/*",
179
+ "sharp"
180
+ ],
181
+ "scanCode": false,
182
+ "failOn": "high"
183
+ }
184
+ ```
185
+
186
+ ### Configuration Options
187
+
188
+ | Option | Type | Description |
189
+ |--------|------|-------------|
190
+ | `ignoredPackages` | `string[]` | Packages to skip (supports `*` wildcards) |
191
+ | `ignoredRules` | `string[]` | Rule IDs to ignore |
192
+ | `trustedPackages` | `string[]` | Packages with reduced severity for install scripts |
193
+ | `scanCode` | `boolean` | Enable deep code scanning by default |
194
+ | `failOn` | `string` | Default fail threshold |
195
+
196
+ ## GitHub Actions Integration
197
+
198
+ ### Basic Usage (Safe Mode)
199
+
200
+ ```yaml
201
+ name: Security Scan
202
+ on: [push, pull_request]
203
+
204
+ jobs:
205
+ supply-chain-scan:
206
+ runs-on: ubuntu-latest
207
+ steps:
208
+ - uses: actions/checkout@v4
209
+
210
+ - name: Setup Node.js
211
+ uses: actions/setup-node@v4
212
+ with:
213
+ node-version: '20'
214
+
215
+ # Install WITHOUT running postinstall scripts (safe)
216
+ - name: Install dependencies (no scripts)
217
+ run: npm ci --ignore-scripts
218
+
219
+ # Scan BEFORE any install scripts execute
220
+ - name: Run chain-audit
221
+ run: npx chain-audit --fail-on high
222
+
223
+ # Only rebuild if scan passes
224
+ - name: Run install scripts
225
+ run: npm rebuild
226
+ ```
227
+
228
+ ### With SARIF Upload (GitHub Code Scanning)
229
+
230
+ ```yaml
231
+ name: Security Scan
232
+ on: [push, pull_request]
233
+
234
+ jobs:
235
+ supply-chain-scan:
236
+ runs-on: ubuntu-latest
237
+ permissions:
238
+ security-events: write
239
+ steps:
240
+ - uses: actions/checkout@v4
241
+
242
+ - name: Setup Node.js
243
+ uses: actions/setup-node@v4
244
+ with:
245
+ node-version: '20'
246
+
247
+ - name: Install dependencies (no scripts)
248
+ run: npm ci --ignore-scripts
249
+
250
+ - name: Run chain-audit
251
+ run: npx chain-audit --sarif > chain-audit.sarif
252
+ continue-on-error: true
253
+
254
+ - name: Upload SARIF
255
+ uses: github/codeql-action/upload-sarif@v3
256
+ with:
257
+ sarif_file: chain-audit.sarif
258
+ category: supply-chain
259
+
260
+ - name: Run install scripts
261
+ run: npm rebuild
262
+ ```
263
+
264
+ ### Using Reusable Workflow (Experimental)
265
+
266
+ Instead of copying workflow code, use the reusable workflow from this repository:
267
+
268
+ ```yaml
269
+ name: Supply Chain Scan
270
+ on: [push, pull_request]
271
+
272
+ jobs:
273
+ scan:
274
+ uses: hukasx0/chain-audit/.github/workflows/scan.yml@main
275
+ with:
276
+ fail-on: high
277
+ scan-code: false
278
+ upload-sarif: true
279
+ ```
280
+
281
+ **Available inputs:**
282
+ - `node-modules-path` (default: `./node_modules`) – Path to node_modules directory
283
+ - `fail-on` (default: `high`) – Severity threshold to fail on (info|low|medium|high|critical)
284
+ - `scan-code` (default: `false`) – Enable deep code scanning (slower)
285
+ - `upload-sarif` (default: `true`) – Upload SARIF to GitHub Code Scanning
286
+
287
+ The reusable workflow automatically uses `--ignore-scripts` for safe installation.
288
+
289
+ ### Monorepo Example
290
+
291
+ ```yaml
292
+ - name: Scan all workspaces
293
+ run: |
294
+ for pkg in packages/*/; do
295
+ if [ -d "${pkg}node_modules" ]; then
296
+ echo "Scanning $pkg"
297
+ npx chain-audit -n "${pkg}node_modules" --fail-on high
298
+ fi
299
+ done
300
+ ```
301
+
302
+ ### ⚠️ CI/CD Security Best Practices
303
+
304
+ Supply chain attacks like [Shai-Hulud 2.0](https://www.wiz.io/blog/shai-hulud-2-0-aftermath-ongoing-supply-chain-attack) exploited misconfigured GitHub Actions. **Protect your CI/CD:**
305
+
306
+ ```yaml
307
+ # ❌ DANGEROUS - Don't use pull_request_target with checkout
308
+ on: pull_request_target # Gives write access + secrets to fork PRs!
309
+
310
+ # ✅ SAFE - Use pull_request (no secrets exposed to forks)
311
+ on: pull_request
312
+ ```
313
+
314
+ **Security checklist:**
315
+ - [ ] **Never use `pull_request_target`** with `actions/checkout` – it exposes secrets to malicious PRs
316
+ - [ ] **Minimize permissions** – use `permissions: read-all` or specific minimal permissions
317
+ - [ ] **Don't pass secrets to npm scripts** – malicious postinstall can read `process.env`
318
+ - [ ] **Use `--ignore-scripts`** – run chain-audit before `npm rebuild`
319
+ - [ ] **Pin action versions** – use `@v4` or SHA, not `@main`
320
+ - [ ] **Review workflow changes** – require approval for `.github/workflows` modifications
321
+
322
+ ```yaml
323
+ # Example: Minimal permissions
324
+ permissions:
325
+ contents: read
326
+ # Only add more if absolutely needed
327
+ ```
328
+
329
+ ## Lockfile Support
330
+
331
+ chain-audit automatically detects and parses:
332
+
333
+ | Lockfile | Package Manager |
334
+ |----------|-----------------|
335
+ | `package-lock.json` | npm v2/v3 |
336
+ | `npm-shrinkwrap.json` | npm |
337
+ | `yarn.lock` | Yarn Classic & Berry |
338
+ | `pnpm-lock.yaml` | pnpm |
339
+ | `bun.lock` | Bun |
340
+
341
+ ## Detection Rules
342
+
343
+ ### Critical Severity
344
+ - **extraneous_package** – Package in node_modules not in lockfile
345
+ - **version_mismatch** – Installed version differs from lockfile
346
+ - **pipe_to_shell** – Script pipes content to shell (`| bash`)
347
+ - **potential_env_exfiltration** – Env access + network in install script
348
+ - **env_with_network** – Code accesses env vars and has network/exec capabilities
349
+ - **obfuscated_code** – Base64/hex encoded strings, char code arrays
350
+
351
+ ### High Severity
352
+ - **network_access_script** – Install script with curl/wget/fetch patterns
353
+ - **potential_typosquat** – Package name similar to popular package
354
+ - **suspicious_name_pattern** – Package name uses character substitution (l33t speak)
355
+ - **eval_usage** – Code uses eval() or new Function()
356
+ - **sensitive_path_access** – Code accesses ~/.ssh, ~/.aws, etc.
357
+ - **shell_execution** – Script executes shell commands
358
+
359
+ ### Medium Severity
360
+ - **install_script** – Has preinstall/install/postinstall/prepare script
361
+ - **code_execution** – Script runs code via node -e, python -c, etc.
362
+ - **child_process_usage** – Code uses child_process module
363
+ - **node_network_access** – Code uses Node.js network APIs (fetch, https, axios)
364
+ - **git_operation_install** – Install script performs git operations
365
+
366
+ ### Low/Info Severity
367
+ - **native_binary** – Contains .node, .so, .dll, .dylib files
368
+ - **no_repository** – No repository URL in package.json
369
+ - **minimal_metadata** – Very short/missing description
370
+
371
+ ## Programmatic Usage
372
+
373
+ ```javascript
374
+ const { run } = require('chain-audit');
375
+
376
+ const result = await run(['node', 'script.js', '--json', '--fail-on', 'high']);
377
+
378
+ console.log(result.exitCode); // 0 or 1
379
+ console.log(result.issues); // Array of issues found
380
+ console.log(result.summary); // { counts: {...}, maxSeverity: 'high' }
381
+ ```
382
+
383
+ ## Best Practices
384
+
385
+ ### ⚠️ Important: When to Run chain-audit
386
+
387
+ **Problem:** If you run chain-audit *after* `npm install`, malicious `postinstall` scripts have already executed – it's too late!
388
+
389
+ **Solution:** Install without running scripts, scan, then rebuild:
390
+
391
+ ```bash
392
+ # 1. Install WITHOUT running lifecycle scripts
393
+ npm ci --ignore-scripts
394
+
395
+ # 2. Scan for malicious packages
396
+ npx chain-audit --fail-on high
397
+
398
+ # 3. If clean, run the install scripts
399
+ npm rebuild
400
+ ```
401
+
402
+ > ⚠️ **Warning:** Even with `--ignore-scripts`, there is no 100% guarantee of security. Malicious code could execute when the package is `require()`d, or exploit vulnerabilities during extraction. For maximum security:
403
+ > - Run installation in a **sandboxed environment**: Docker, Podman, or a VM (VirtualBox, VMware, QEMU/KVM)
404
+ > - Use ephemeral CI runners (GitHub Actions, GitLab CI) that are destroyed after each run
405
+ > - Never install untrusted packages on production or development machines directly
406
+
407
+ ### General Guidelines
408
+
409
+ 1. **Always use lockfiles** – Run `npm ci` instead of `npm install` in CI
410
+ 2. **Use `--ignore-scripts` + chain-audit + rebuild** – Scan before scripts execute
411
+ 3. **Run in sandboxed CI** – Isolate potentially malicious code
412
+ 4. **Combine with npm audit** – chain-audit detects different threats
413
+ 5. **Review all findings** – Some may be false positives
414
+ 6. **Use `--scan-code` periodically** – More thorough but slower
415
+ 7. **Keep registry secure** – Use private registry or npm audit signatures
416
+
417
+ ## Contributing
418
+
419
+ **Repository:** [github.com/hukasx0/chain-audit](https://github.com/hukasx0/chain-audit)
420
+
421
+ ```bash
422
+ # Clone and install
423
+ git clone https://github.com/hukasx0/chain-audit.git
424
+ cd chain-audit
425
+ npm install
426
+
427
+ # Run linter
428
+ npm run lint
429
+
430
+ # Run tests
431
+ npm test
432
+
433
+ # Test on a real project
434
+ node src/index.js --node-modules /path/to/project/node_modules
435
+ ```
436
+
437
+ ## License
438
+
439
+ Hubert Kasperek
440
+
441
+ [MIT License](https://github.com/Hukasx0/chain-audit-private/blob/main/LICENSE)
442
+
443
+ ---
444
+
445
+ **⚠️ Disclaimer:** chain-audit is a heuristic scanner created for **educational and research purposes**, provided "AS IS" without warranty of any kind. It may produce false positives and **cannot catch all attacks**. Even with `--ignore-scripts`, malicious packages could execute code on `require()` etc.
446
+
447
+ **The author(s) take no responsibility for:**
448
+ - False positives or false negatives in detection
449
+ - Missed malicious packages or vulnerabilities
450
+ - Any damages resulting from use or inability to use this tool
451
+ - Security incidents that occur despite using this tool
452
+ - and more
453
+
454
+ **By using chain-audit, you accept full responsibility for your actions and security decisions.**
455
+
456
+ **Always:**
457
+ - Install dependencies in isolated environments (Docker, VirtualBox, VMware, QEMU/KVM)
458
+ - Review findings manually
459
+ - Use as part of a defense-in-depth security strategy
460
+ - Never trust any single tool as your only line of defense
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "chain-audit",
3
+ "version": "0.5.0",
4
+ "description": "Fast, zero-dependency CLI to detect supply chain attacks in node_modules. Scans for malicious install scripts, typosquatting, extraneous packages, and suspicious code patterns.",
5
+ "main": "src/index.js",
6
+ "bin": {
7
+ "chain-audit": "src/index.js"
8
+ },
9
+ "exports": {
10
+ ".": "./src/index.js",
11
+ "./analyzer": "./src/analyzer.js",
12
+ "./collector": "./src/collector.js",
13
+ "./lockfile": "./src/lockfile.js"
14
+ },
15
+ "files": [
16
+ "src/**/*.js",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "start": "node src/index.js",
22
+ "scan": "node src/index.js",
23
+ "scan:json": "node src/index.js --json",
24
+ "scan:sarif": "node src/index.js --sarif",
25
+ "scan:deep": "node src/index.js --scan-code",
26
+ "lint": "eslint src/",
27
+ "lint:fix": "eslint src/ --fix",
28
+ "test": "node --test test/*.test.js",
29
+ "prepublishOnly": "npm run lint"
30
+ },
31
+ "keywords": [
32
+ "security",
33
+ "supply-chain",
34
+ "supply-chain-attack",
35
+ "node-modules",
36
+ "audit",
37
+ "malware",
38
+ "dependency",
39
+ "npm-audit",
40
+ "postinstall",
41
+ "typosquatting",
42
+ "ci",
43
+ "github-actions",
44
+ "sarif"
45
+ ],
46
+ "author": "Hubert Kasperek",
47
+ "license": "MIT",
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/hukasx0/chain-audit.git"
51
+ },
52
+ "bugs": {
53
+ "url": "https://github.com/hukasx0/chain-audit/issues"
54
+ },
55
+ "homepage": "https://github.com/hukasx0/chain-audit#readme",
56
+ "engines": {
57
+ "node": ">=18.0.0"
58
+ },
59
+ "devDependencies": {
60
+ "eslint": "^8.57.0"
61
+ }
62
+ }