chain-audit 0.5.7 → 0.6.1
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 +43 -52
- package/package.json +1 -1
- package/src/analyzer.js +1209 -158
- package/src/cli.js +14 -2
- package/src/config.js +25 -14
- package/src/formatters.js +3 -2
- package/src/index.js +14 -4
package/README.md
CHANGED
|
@@ -7,25 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
**Fast, zero-dependency CLI to detect supply chain attacks in `node_modules`.**
|
|
9
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
10
|
---
|
|
17
11
|
|
|
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
12
|
## Why chain-audit?
|
|
30
13
|
|
|
31
14
|
| Feature | chain-audit | npm audit |
|
|
@@ -108,10 +91,10 @@ chain-audit --sarif > results.sarif
|
|
|
108
91
|
chain-audit --scan-code
|
|
109
92
|
|
|
110
93
|
# Detailed analysis with code snippets and evidence
|
|
111
|
-
chain-audit --
|
|
94
|
+
chain-audit --detailed --scan-code
|
|
112
95
|
|
|
113
|
-
#
|
|
114
|
-
chain-audit --
|
|
96
|
+
# Detailed output as JSON for further processing
|
|
97
|
+
chain-audit --detailed --json --scan-code
|
|
115
98
|
|
|
116
99
|
# Ignore specific packages and rules
|
|
117
100
|
chain-audit --ignore-packages "@types/*" --ignore-rules native_binary
|
|
@@ -120,10 +103,13 @@ chain-audit --ignore-packages "@types/*" --ignore-rules native_binary
|
|
|
120
103
|
chain-audit --verify-integrity --fail-on high
|
|
121
104
|
|
|
122
105
|
# Deep scan with no file limit
|
|
123
|
-
chain-audit --scan-code --max-files 0 --
|
|
106
|
+
chain-audit --scan-code --max-files 0 --detailed
|
|
124
107
|
|
|
125
108
|
# Custom scan limits
|
|
126
109
|
chain-audit --max-file-size 2097152 --max-depth 15
|
|
110
|
+
|
|
111
|
+
# Enable typosquatting detection (disabled by default)
|
|
112
|
+
chain-audit --check-typosquatting
|
|
127
113
|
```
|
|
128
114
|
|
|
129
115
|
## CLI Options
|
|
@@ -138,7 +124,7 @@ chain-audit --max-file-size 2097152 --max-depth 15
|
|
|
138
124
|
| `-s, --severity <levels>` | Show only specified severity levels (comma-separated, e.g., `critical,high`) |
|
|
139
125
|
| `--fail-on <level>` | Exit 1 if max severity >= level |
|
|
140
126
|
| `--scan-code` | Deep scan JS files for suspicious patterns |
|
|
141
|
-
| `-V, --
|
|
127
|
+
| `-V, --detailed` | Show detailed analysis: code snippets with line numbers, matched patterns, package metadata, trust assessment, false positive hints, and verification steps (`--verbose` is an alias for backward compatibility) |
|
|
142
128
|
| `-v, --version` | Print version |
|
|
143
129
|
| `-h, --help` | Show help |
|
|
144
130
|
| `--init` | Generate example config file (`.chainauditrc.json`) |
|
|
@@ -152,6 +138,8 @@ chain-audit --max-file-size 2097152 --max-depth 15
|
|
|
152
138
|
| `--max-depth <n>` | Max nested node_modules depth (default: 10) |
|
|
153
139
|
| `--max-files <n>` | Max JS files to scan per package (0 = unlimited, default: 0) |
|
|
154
140
|
| `--verify-integrity` | Additional checks for package structure tampering |
|
|
141
|
+
| `--check-typosquatting` | Enable typosquatting detection (disabled by default) |
|
|
142
|
+
| `--check-lockfile` | Check lockfile integrity (disabled by default due to possible false positives) |
|
|
155
143
|
|
|
156
144
|
## Severity Levels
|
|
157
145
|
|
|
@@ -161,7 +149,7 @@ chain-audit --max-file-size 2097152 --max-depth 15
|
|
|
161
149
|
| `high` | Strong attack indicators | Suspicious install scripts with network/exec, typosquatting |
|
|
162
150
|
| `medium` | Warrants investigation | Install scripts, shell execution patterns |
|
|
163
151
|
| `low` | Informational | Native binaries, minimal metadata |
|
|
164
|
-
| `info` | Metadata only |
|
|
152
|
+
| `info` | Metadata only | Packages with install scripts that match trusted patterns (if configured) |
|
|
165
153
|
|
|
166
154
|
### Filtering by Severity
|
|
167
155
|
|
|
@@ -186,7 +174,7 @@ Issues will be displayed in the order they are found, grouped by the severity le
|
|
|
186
174
|
## Example Output
|
|
187
175
|
|
|
188
176
|
```
|
|
189
|
-
chain-audit v0.
|
|
177
|
+
chain-audit v0.6.1
|
|
190
178
|
────────────────────────────────────────────────────────────
|
|
191
179
|
|
|
192
180
|
node_modules: /path/to/project/node_modules
|
|
@@ -221,13 +209,15 @@ Summary:
|
|
|
221
209
|
Max severity: CRITICAL
|
|
222
210
|
```
|
|
223
211
|
|
|
224
|
-
##
|
|
212
|
+
## Detailed Mode (`--detailed`)
|
|
225
213
|
|
|
226
|
-
The `--
|
|
214
|
+
The `--detailed` (`-V`) option provides detailed analysis to investigate findings and distinguish false positives from real threats.
|
|
215
|
+
|
|
216
|
+
> **Note:** `--verbose` is an alias for `--detailed` and is supported for backward compatibility.
|
|
227
217
|
|
|
228
218
|
### What's Included
|
|
229
219
|
|
|
230
|
-
When `--
|
|
220
|
+
When `--detailed` is enabled, each finding includes:
|
|
231
221
|
|
|
232
222
|
- **Code snippets** with line numbers showing exactly where issues were detected (3 lines of context before/after)
|
|
233
223
|
- **Matched patterns** (regex) that triggered the detection
|
|
@@ -244,15 +234,17 @@ The trust score (0-100) is calculated based on multiple factors:
|
|
|
244
234
|
|
|
245
235
|
| Factor | Points | Description |
|
|
246
236
|
|--------|--------|-------------|
|
|
247
|
-
| **Trusted scope** | +40 | Package is from a
|
|
248
|
-
| **Known legitimate** | +50 | Package is in the
|
|
237
|
+
| **Trusted scope** | +40 | Package is from a scope listed in `trustedPackages` config (if configured) |
|
|
238
|
+
| **Known legitimate** | +50 | Package is in the `trustedPackages` config list (if configured) |
|
|
249
239
|
| **Has repository** | +20 | Package has a repository URL in package.json |
|
|
250
240
|
| **Has homepage** | +10 | Package has a homepage URL |
|
|
251
241
|
| **Has author** | +10 | Package has author information |
|
|
252
242
|
| **Has license** | +10 | Package has a license field |
|
|
253
243
|
|
|
244
|
+
**Note:** By default, no packages are whitelisted. All packages are checked with equal severity. You can configure `trustedPackages` in `.chainauditrc.json` if you need to reduce false positives for specific packages.
|
|
245
|
+
|
|
254
246
|
**Trust Levels:**
|
|
255
|
-
- **High (70-100)**: Package is likely legitimate (e.g.,
|
|
247
|
+
- **High (70-100)**: Package is likely legitimate (e.g., configured as trusted with repository)
|
|
256
248
|
- **Medium (40-69)**: Package has some trust indicators but needs verification
|
|
257
249
|
- **Low (0-39)**: Package lacks trust indicators, warrants closer investigation
|
|
258
250
|
|
|
@@ -267,7 +259,7 @@ Trust Assessment:
|
|
|
267
259
|
✗ No repository
|
|
268
260
|
```
|
|
269
261
|
|
|
270
|
-
### When to Use
|
|
262
|
+
### When to Use Detailed Mode
|
|
271
263
|
|
|
272
264
|
- **Manual investigation** of suspicious findings
|
|
273
265
|
- **Creating security reports** with detailed evidence
|
|
@@ -308,15 +300,16 @@ Alternatively, you can manually create a config file in your project root. Suppo
|
|
|
308
300
|
"native_binary"
|
|
309
301
|
],
|
|
310
302
|
"trustedPackages": [
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
"sharp"
|
|
303
|
+
// Empty by default - all packages are checked without exceptions
|
|
304
|
+
// Add packages here only if you need to reduce false positives for specific packages
|
|
305
|
+
// Example: "esbuild", "@swc/*", "sharp"
|
|
314
306
|
],
|
|
315
307
|
"trustedPatterns": {
|
|
316
308
|
"node-gyp rebuild": true,
|
|
317
309
|
"prebuild-install": true
|
|
318
310
|
},
|
|
319
311
|
"scanCode": false,
|
|
312
|
+
"checkTyposquatting": false,
|
|
320
313
|
"failOn": "high",
|
|
321
314
|
"severity": ["critical", "high"],
|
|
322
315
|
"format": "text",
|
|
@@ -334,13 +327,14 @@ Alternatively, you can manually create a config file in your project root. Suppo
|
|
|
334
327
|
|--------|------|---------|-------------|
|
|
335
328
|
| `ignoredPackages` | `string[]` | `[]` | Packages to skip (supports `*` wildcards) |
|
|
336
329
|
| `ignoredRules` | `string[]` | `[]` | Rule IDs to ignore |
|
|
337
|
-
| `trustedPackages` | `string[]` | `[
|
|
330
|
+
| `trustedPackages` | `string[]` | `[]` | Packages with reduced severity for install scripts (empty by default - all packages are checked) |
|
|
338
331
|
| `trustedPatterns` | `object` | `{node-gyp rebuild: true, ...}` | Install script patterns considered safe |
|
|
339
332
|
| `scanCode` | `boolean` | `false` | Enable deep code scanning by default |
|
|
333
|
+
| `checkTyposquatting` | `boolean` | `false` | Enable typosquatting detection (disabled by default to reduce false positives) |
|
|
340
334
|
| `failOn` | `string` | `null` | Default fail threshold (`info\|low\|medium\|high\|critical`) |
|
|
341
335
|
| `severity` | `string[]` | `null` | Show only specified severity levels (e.g., `["critical", "high"]`) |
|
|
342
336
|
| `format` | `string` | `"text"` | Output format: `text`, `json`, or `sarif` |
|
|
343
|
-
| `verbose` | `boolean` | `false` | Show detailed analysis with code snippets and trust scores |
|
|
337
|
+
| `verbose` | `boolean` | `false` | Show detailed analysis with code snippets and trust scores (Note: CLI flag is `--detailed`, but config uses `verbose` for consistency) |
|
|
344
338
|
| `maxFileSizeForCodeScan` | `number` | `1048576` | Max file size (bytes) to scan for code patterns |
|
|
345
339
|
| `maxNestedDepth` | `number` | `10` | Max depth to traverse nested node_modules |
|
|
346
340
|
| `maxFilesPerPackage` | `number` | `0` | Max JS files to scan per package (0 = unlimited) |
|
|
@@ -452,15 +446,15 @@ The reusable workflow automatically uses `--ignore-scripts` for safe installatio
|
|
|
452
446
|
done
|
|
453
447
|
```
|
|
454
448
|
|
|
455
|
-
###
|
|
449
|
+
### CI/CD Security Best Practices
|
|
456
450
|
|
|
457
451
|
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:**
|
|
458
452
|
|
|
459
453
|
```yaml
|
|
460
|
-
#
|
|
454
|
+
# DANGEROUS - Don't use pull_request_target with checkout
|
|
461
455
|
on: pull_request_target # Gives write access + secrets to fork PRs!
|
|
462
456
|
|
|
463
|
-
#
|
|
457
|
+
# SAFE - Use pull_request (no secrets exposed to forks)
|
|
464
458
|
on: pull_request
|
|
465
459
|
```
|
|
466
460
|
|
|
@@ -508,8 +502,8 @@ chain-audit automatically detects and parses:
|
|
|
508
502
|
|
|
509
503
|
### High Severity
|
|
510
504
|
- **network_access_script** – Install script with curl/wget/fetch patterns
|
|
511
|
-
- **potential_typosquat** – Package name similar to popular package
|
|
512
|
-
- **suspicious_name_pattern** – Package name uses character substitution (l33t speak)
|
|
505
|
+
- **potential_typosquat** – Package name similar to popular package (requires `--check-typosquatting`)
|
|
506
|
+
- **suspicious_name_pattern** – Package name uses character substitution (l33t speak) (requires `--check-typosquatting`)
|
|
513
507
|
- **eval_usage** – Code uses eval() or new Function()
|
|
514
508
|
- **sensitive_path_access** – Code accesses ~/.ssh, ~/.aws, etc.
|
|
515
509
|
- **shell_execution** – Script executes shell commands
|
|
@@ -540,7 +534,7 @@ console.log(result.summary); // { counts: {...}, maxSeverity: 'high' }
|
|
|
540
534
|
|
|
541
535
|
## Best Practices
|
|
542
536
|
|
|
543
|
-
###
|
|
537
|
+
### Important: When to Run chain-audit
|
|
544
538
|
|
|
545
539
|
**Problem:** If you run chain-audit *after* `npm install`, malicious `postinstall` scripts have already executed – it's too late!
|
|
546
540
|
|
|
@@ -557,7 +551,9 @@ npx chain-audit --fail-on high
|
|
|
557
551
|
npm rebuild
|
|
558
552
|
```
|
|
559
553
|
|
|
560
|
-
>
|
|
554
|
+
> 💡 **Note:** chain-audit analyzes scripts by reading them from `package.json` files (static analysis), not by executing them. This means it can detect malicious scripts even when using `--ignore-scripts`, because it reads the script content as text and checks for suspicious patterns
|
|
555
|
+
|
|
556
|
+
> **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:
|
|
561
557
|
> - Run installation in a **sandboxed environment**: Docker, Podman, or a VM (VirtualBox, VMware, QEMU/KVM)
|
|
562
558
|
> - Use ephemeral CI runners (GitHub Actions, GitLab CI) that are destroyed after each run
|
|
563
559
|
> - Never install untrusted packages on production or development machines directly
|
|
@@ -570,8 +566,9 @@ npm rebuild
|
|
|
570
566
|
4. **Combine with npm audit** – chain-audit detects different threats
|
|
571
567
|
5. **Review all findings** – Some may be false positives
|
|
572
568
|
6. **Use `--scan-code` periodically** – More thorough but slower
|
|
573
|
-
7. **Use `--
|
|
569
|
+
7. **Use `--detailed` for manual investigation** – Get code snippets and trust assessment to distinguish false positives (`--verbose` is an alias)
|
|
574
570
|
8. **Keep registry secure** – Use private registry or npm audit signatures
|
|
571
|
+
9. **All packages are checked equally** – No packages are whitelisted by default. Even popular packages like `sharp`, `esbuild`, or `@babel/*` are checked for malicious patterns. This ensures that compromised packages are detected regardless of their reputation.
|
|
575
572
|
|
|
576
573
|
## Contributing
|
|
577
574
|
|
|
@@ -601,9 +598,9 @@ Hubert Kasperek
|
|
|
601
598
|
|
|
602
599
|
---
|
|
603
600
|
|
|
604
|
-
|
|
601
|
+
**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**.
|
|
605
602
|
|
|
606
|
-
**The author
|
|
603
|
+
**The author takes no responsibility for:**
|
|
607
604
|
- False positives or false negatives in detection
|
|
608
605
|
- Missed malicious packages or vulnerabilities
|
|
609
606
|
- Any damages resulting from use or inability to use this tool
|
|
@@ -611,9 +608,3 @@ Hubert Kasperek
|
|
|
611
608
|
- and more
|
|
612
609
|
|
|
613
610
|
**By using chain-audit, you accept full responsibility for your actions and security decisions.**
|
|
614
|
-
|
|
615
|
-
**Always:**
|
|
616
|
-
- Install dependencies in isolated environments (Docker, VirtualBox, VMware, QEMU/KVM)
|
|
617
|
-
- Review findings manually
|
|
618
|
-
- Use as part of a defense-in-depth security strategy
|
|
619
|
-
- Never trust any single tool as your only line of defense
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chain-audit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
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
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|