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 +21 -0
- package/README.md +460 -0
- package/package.json +62 -0
- package/src/analyzer.js +787 -0
- package/src/cli.js +127 -0
- package/src/collector.js +193 -0
- package/src/config.js +163 -0
- package/src/formatters.js +392 -0
- package/src/index.js +251 -0
- package/src/lockfile.js +539 -0
- package/src/utils.js +94 -0
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
|
+
[](https://github.com/hukasx0/chain-audit/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/chain-audit)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](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
|
+
}
|