pnpm-audit-hook 1.0.0 → 1.0.2

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 +408 -137
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,30 +1,234 @@
1
1
  # pnpm-audit-hook
2
2
 
3
- A pnpm hook that audits dependencies for vulnerabilities **before packages are downloaded**. It queries the GitHub Advisory Database for vulnerabilities and optionally enriches severity data from NVD, blocking installs when critical or high severity issues are found.
3
+ A pnpm hook that audits dependencies for vulnerabilities **before packages are downloaded**. It queries the GitHub Advisory Database and uses a bundled static vulnerability database, blocking installs when critical or high severity issues are found.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ pnpm add -D pnpm-audit-hook && pnpm exec pnpm-audit-setup
9
+ ```
10
+
11
+ Done! Every `pnpm install` will now audit packages before downloading.
12
+
13
+ ## How It Works
14
+
15
+ ### Overview
16
+
17
+ ```mermaid
18
+ flowchart LR
19
+ A[pnpm install] --> B[Resolve Dependencies]
20
+ B --> C[.pnpmfile.cjs Hook]
21
+ C --> D{Audit Packages}
22
+ D -->|Safe| E[Download & Install]
23
+ D -->|Vulnerable| F[Block Install]
24
+ ```
25
+
26
+ When you run `pnpm install`, the hook intercepts the process **after dependency resolution but before downloading**. This means vulnerable packages are blocked without ever being downloaded to your machine.
27
+
28
+ ### Detailed Flow
29
+
30
+ ```mermaid
31
+ flowchart TD
32
+ subgraph PNPM["pnpm install"]
33
+ A[Start] --> B[Resolve dependency graph]
34
+ B --> C[Generate lockfile]
35
+ end
36
+
37
+ subgraph HOOK["pnpm-audit-hook"]
38
+ C --> D[".pnpmfile.cjs<br/>afterAllResolved()"]
39
+ D --> E[Extract packages from lockfile]
40
+ E --> F[Load config from .pnpm-audit.yaml]
41
+ F --> G{Check cache}
42
+ G -->|Cache hit| H[Use cached results]
43
+ G -->|Cache miss| I[Query vulnerability sources]
44
+
45
+ subgraph SOURCES["Vulnerability Sources"]
46
+ I --> J[Static DB<br/>Historical vulns]
47
+ I --> K[GitHub Advisory API<br/>Recent vulns]
48
+ J --> L[Merge & deduplicate]
49
+ K --> L
50
+ L --> M{Unknown severity?}
51
+ M -->|Yes| N[Enrich from NVD]
52
+ M -->|No| O[Continue]
53
+ N --> O
54
+ end
55
+
56
+ H --> P[Apply policy rules]
57
+ O --> P
58
+ P --> Q{Check allowlist}
59
+ Q -->|Allowed| R[Skip]
60
+ Q -->|Not allowed| S{Severity check}
61
+ S -->|critical/high| T[BLOCK]
62
+ S -->|medium/low| U[WARN]
63
+ S -->|unknown| U
64
+ end
65
+
66
+ subgraph RESULT["Result"]
67
+ T --> V[Throw error<br/>Abort install]
68
+ U --> W[Log warnings]
69
+ R --> W
70
+ W --> X[Continue install]
71
+ X --> Y[Download packages]
72
+ end
73
+ ```
74
+
75
+ ### Installation Changes
76
+
77
+ When you run `pnpm exec pnpm-audit-setup`, these files are created in your project:
78
+
79
+ | File | Purpose |
80
+ |------|---------|
81
+ | `.pnpmfile.cjs` | pnpm hook entry point - intercepts `pnpm install` |
82
+ | `.pnpm-audit.yaml` | Optional configuration file (created if missing) |
83
+ | `.pnpm-audit-cache/` | Cache directory (created automatically at runtime) |
84
+
85
+ ### File Structure After Installation
86
+
87
+ ```
88
+ your-project/
89
+ ├── .pnpmfile.cjs # Hook that pnpm loads automatically
90
+ ├── .pnpm-audit.yaml # Your security policy config (optional)
91
+ ├── .pnpm-audit-cache/ # Cached vulnerability data (auto-created)
92
+ ├── node_modules/
93
+ │ └── pnpm-audit-hook/ # The installed package
94
+ │ ├── dist/ # Compiled audit logic
95
+ │ └── .pnpmfile.cjs # Template hook file
96
+ ├── package.json
97
+ └── pnpm-lock.yaml
98
+ ```
99
+
100
+ ## Vulnerability Sources
101
+
102
+ ```mermaid
103
+ flowchart TD
104
+ subgraph PRIMARY["Primary Source"]
105
+ A[Static Database] --> C[Merged Results]
106
+ B[GitHub Advisory API] --> C
107
+ end
108
+
109
+ subgraph ENRICHMENT["Severity Enrichment"]
110
+ C --> D{Severity = unknown?}
111
+ D -->|Yes| E[Query NVD API]
112
+ D -->|No| F[Final Results]
113
+ E --> F
114
+ end
115
+
116
+ style A fill:#90EE90
117
+ style B fill:#87CEEB
118
+ style E fill:#FFE4B5
119
+ ```
120
+
121
+ | Source | Type | Description | Rate Limits |
122
+ |--------|------|-------------|-------------|
123
+ | **Static DB** | Bundled | Historical vulnerabilities (2020-2025), works offline | None |
124
+ | **GitHub Advisory** | API | Real-time vulnerability data from GHSA | 60/hr (no token), 5000/hr (with token) |
125
+ | **NVD** | API | Severity enrichment only (CVSS scores) | 5/30s (no key), 50/30s (with key) |
126
+
127
+ ### Query Strategy
128
+
129
+ ```mermaid
130
+ sequenceDiagram
131
+ participant H as Hook
132
+ participant C as Cache
133
+ participant S as Static DB
134
+ participant G as GitHub API
135
+ participant N as NVD API
136
+
137
+ H->>C: Check cache for package@version
138
+ alt Cache hit (not expired)
139
+ C-->>H: Return cached vulnerabilities
140
+ else Cache miss
141
+ H->>S: Query historical vulns (before cutoff)
142
+ S-->>H: Historical findings
143
+ H->>G: Query recent vulns (after cutoff)
144
+ G-->>H: Recent findings
145
+ H->>H: Merge & deduplicate
146
+
147
+ opt Has unknown severity
148
+ H->>N: Enrich severity data
149
+ N-->>H: CVSS scores
150
+ end
151
+
152
+ H->>C: Cache results (TTL based on severity)
153
+ end
154
+ ```
155
+
156
+ ## Blocking Policy
157
+
158
+ ### Default Policy
159
+
160
+ ```yaml
161
+ policy:
162
+ block: # Abort install if found
163
+ - critical
164
+ - high
165
+ warn: # Log warning but continue
166
+ - medium
167
+ - low
168
+ - unknown
169
+ ```
170
+
171
+ ### Policy Decision Flow
172
+
173
+ ```mermaid
174
+ flowchart TD
175
+ A[Vulnerability Found] --> B{In allowlist?}
176
+ B -->|Yes, not expired| C[ALLOW - Skip]
177
+ B -->|No or expired| D{Severity level?}
178
+
179
+ D -->|critical| E[BLOCK]
180
+ D -->|high| E
181
+ D -->|medium| F[WARN]
182
+ D -->|low| F
183
+ D -->|unknown| F
184
+
185
+ E --> G[Collect all blocks]
186
+ F --> H[Collect all warnings]
187
+ C --> I[Continue]
188
+
189
+ G --> J{Any blocks?}
190
+ J -->|Yes| K[Throw Error<br/>Abort pnpm install]
191
+ J -->|No| L[Log warnings]
192
+ H --> L
193
+ L --> M[Continue install]
194
+
195
+ style E fill:#FF6B6B
196
+ style F fill:#FFE66D
197
+ style C fill:#90EE90
198
+ style K fill:#FF6B6B
199
+ ```
200
+
201
+ ### Severity Levels
202
+
203
+ | Severity | CVSS Score | Default Action | Example |
204
+ |----------|------------|----------------|---------|
205
+ | **critical** | 9.0 - 10.0 | Block | Remote code execution |
206
+ | **high** | 7.0 - 8.9 | Block | Authentication bypass |
207
+ | **medium** | 4.0 - 6.9 | Warn | Information disclosure |
208
+ | **low** | 0.1 - 3.9 | Warn | Minor information leak |
209
+ | **unknown** | N/A | Warn | Severity not determined |
4
210
 
5
211
  ## Installation
6
212
 
7
- ### From npm/pnpm (Easiest)
213
+ ### Per-Project (Recommended)
8
214
 
9
215
  ```bash
10
- # Install the package
216
+ # 1. Install
11
217
  pnpm add -D pnpm-audit-hook
12
218
 
13
- # Run setup to create .pnpmfile.cjs in your project
219
+ # 2. Setup (creates .pnpmfile.cjs in your project)
14
220
  pnpm exec pnpm-audit-setup
15
221
  ```
16
222
 
17
- That's it! Every `pnpm install` will now audit packages for vulnerabilities.
18
-
19
- ### Global Setup (All Projects)
223
+ ### Global (All Projects)
20
224
 
21
- To enable for all pnpm projects on your machine:
225
+ Enable vulnerability auditing for all pnpm projects on your machine:
22
226
 
23
227
  ```bash
24
228
  # Install globally
25
229
  pnpm add -g pnpm-audit-hook
26
230
 
27
- # Create global hooks directory
231
+ # Create global hooks directory and copy files
28
232
  mkdir -p ~/.pnpm-hooks
29
233
  cp $(pnpm root -g)/pnpm-audit-hook/dist ~/.pnpm-hooks/ -r
30
234
  cp $(pnpm root -g)/pnpm-audit-hook/.pnpmfile.cjs ~/.pnpm-hooks/
@@ -33,7 +237,7 @@ cp $(pnpm root -g)/pnpm-audit-hook/.pnpmfile.cjs ~/.pnpm-hooks/
33
237
  pnpm config set global-pnpmfile ~/.pnpm-hooks/.pnpmfile.cjs
34
238
  ```
35
239
 
36
- ### Manual Setup
240
+ ### From Source
37
241
 
38
242
  ```bash
39
243
  git clone https://github.com/asx8678/pnpm-audit-hook.git
@@ -45,14 +249,34 @@ cp -r dist /path/to/your/project/
45
249
  cp .pnpmfile.cjs /path/to/your/project/
46
250
  ```
47
251
 
48
- ## Quick Test
252
+ ## Verify Installation
49
253
 
50
254
  ```bash
51
- pnpm add lodash # Safe - installs normally
52
- pnpm add event-stream@3.3.6 # Vulnerable - blocked!
255
+ # This should work (safe package)
256
+ pnpm add lodash
257
+
258
+ # This should be BLOCKED (known vulnerable)
259
+ pnpm add event-stream@3.3.6
53
260
  ```
54
261
 
55
- If vulnerabilities are found, install fails before any packages are downloaded.
262
+ If vulnerabilities are found, the install fails **before** any packages are downloaded.
263
+
264
+ ## Uninstall
265
+
266
+ ### Per-Project
267
+
268
+ ```bash
269
+ rm .pnpmfile.cjs
270
+ pnpm remove pnpm-audit-hook
271
+ ```
272
+
273
+ ### Global
274
+
275
+ ```bash
276
+ pnpm config delete global-pnpmfile
277
+ rm -rf ~/.pnpm-hooks
278
+ pnpm remove -g pnpm-audit-hook
279
+ ```
56
280
 
57
281
  ## Configuration
58
282
 
@@ -82,30 +306,27 @@ performance:
82
306
 
83
307
  cache:
84
308
  ttlSeconds: 3600
85
- ```
86
-
87
- All fields are optional. Set any source to `false` to disable it.
88
-
89
- ### Configuration Constraints
90
-
91
- The following validation rules are applied to configuration values:
92
-
93
- | Setting | Constraint | Default |
94
- |---------|------------|---------|
95
- | `performance.timeoutMs` | 1 to 300,000 ms (5 minutes max) | 15,000 |
96
- | `cache.ttlSeconds` | 1 to 86,400 seconds (24 hours max) | 3,600 |
97
- | `staticBaseline.cutoffDate` | Valid ISO date format, must not be in the future | 2025-12-31 |
98
309
 
99
- Invalid values are silently replaced with defaults to ensure safe operation.
310
+ staticBaseline:
311
+ enabled: true
312
+ cutoffDate: "2025-12-31"
313
+ ```
100
314
 
101
- ## Vulnerability Sources
315
+ All fields are optional. Defaults are applied for missing values.
102
316
 
103
- | Source | Description | Auth |
104
- |--------|-------------|------|
105
- | **GitHub Advisory** | Primary source - GitHub Security Advisory database (GHSA) | Optional |
106
- | **NVD** | Severity enrichment only - NIST National Vulnerability Database | Optional |
317
+ ### Configuration Options
107
318
 
108
- GitHub Advisory is the primary vulnerability source. NVD provides additional severity metadata but does not add new vulnerability entries.
319
+ | Option | Description | Default |
320
+ |--------|-------------|---------|
321
+ | `policy.block` | Severities that abort install | `["critical", "high"]` |
322
+ | `policy.warn` | Severities that log warnings | `["medium", "low", "unknown"]` |
323
+ | `policy.allowlist` | Exceptions to skip | `[]` |
324
+ | `sources.github` | Enable GitHub Advisory | `true` |
325
+ | `sources.nvd` | Enable NVD enrichment | `true` |
326
+ | `performance.timeoutMs` | API timeout (1-300,000) | `15000` |
327
+ | `cache.ttlSeconds` | Cache duration (1-86,400) | `3600` |
328
+ | `staticBaseline.enabled` | Use bundled vuln database | `true` |
329
+ | `staticBaseline.cutoffDate` | Static DB coverage date | `2025-12-31` |
109
330
 
110
331
  ## Allowlist
111
332
 
@@ -114,42 +335,78 @@ Suppress specific vulnerabilities or packages:
114
335
  ```yaml
115
336
  policy:
116
337
  allowlist:
338
+ # By CVE/GHSA ID
117
339
  - id: CVE-2024-12345
118
340
  reason: "False positive for our use case"
341
+
342
+ # By package name
119
343
  - package: legacy-lib
120
344
  reason: "Accepted risk"
121
345
  expires: "2025-06-01"
346
+
347
+ # Scoped: specific CVE in specific package
348
+ - id: CVE-2024-12345
349
+ package: affected-pkg
350
+ version: ">=1.0.0 <2.0.0" # Optional version constraint
351
+ reason: "Only affects unused feature"
122
352
  ```
123
353
 
124
- - `id` - CVE or GHSA identifier to ignore (case-insensitive)
125
- - `package` - Package name to ignore entirely (case-insensitive)
126
- - If both `id` and `package` are set, **both must match** (scoped allowlist)
127
- - `reason` - Why it's allowed (for audit trail)
128
- - `expires` - ISO date when the allowlist entry expires
354
+ | Field | Required | Description |
355
+ |-------|----------|-------------|
356
+ | `id` | One of id/package | CVE or GHSA identifier (case-insensitive) |
357
+ | `package` | One of id/package | Package name to ignore (case-insensitive) |
358
+ | `version` | No | Semver range constraint |
359
+ | `reason` | No | Audit trail documentation |
360
+ | `expires` | No | ISO date when entry expires |
129
361
 
130
362
  ## Environment Variables
131
363
 
132
364
  | Variable | Description |
133
365
  |----------|-------------|
134
- | `PNPM_AUDIT_CONFIG_PATH` | Override config file location |
366
+ | `GITHUB_TOKEN` / `GH_TOKEN` | GitHub API token (higher rate limits) |
367
+ | `NVD_API_KEY` / `NIST_NVD_API_KEY` | NVD API key (higher rate limits) |
368
+ | `PNPM_AUDIT_CONFIG_PATH` | Custom config file location |
135
369
  | `PNPM_AUDIT_DISABLE_GITHUB` | Disable GitHub Advisory source |
136
- | `GITHUB_TOKEN` | GitHub API token (optional) |
137
- | `GH_TOKEN` | Alternative to GITHUB_TOKEN |
138
- | `NVD_API_KEY` | NVD API key (optional) |
139
- | `NIST_NVD_API_KEY` | Alternative to NVD_API_KEY |
140
- | `PNPM_AUDIT_QUIET` | Suppress info/warn output (`true` to enable) |
141
- | `PNPM_AUDIT_DEBUG` | Enable debug logging (`true` to enable) |
142
- | `PNPM_AUDIT_JSON` | Enable JSON output format (`true` to enable) |
370
+ | `PNPM_AUDIT_QUIET` | Suppress info/warn output |
371
+ | `PNPM_AUDIT_DEBUG` | Enable debug logging |
372
+ | `PNPM_AUDIT_JSON` | JSON output format |
373
+
374
+ ## Caching
375
+
376
+ ```mermaid
377
+ flowchart LR
378
+ A[Package Query] --> B{Cache exists?}
379
+ B -->|Yes| C{Expired?}
380
+ C -->|No| D[Return cached]
381
+ C -->|Yes| E[Query APIs]
382
+ B -->|No| E
383
+ E --> F[Cache with TTL]
384
+ F --> G[Return results]
385
+
386
+ style D fill:#90EE90
387
+ ```
143
388
 
144
- ## How It Works
389
+ ### Cache Location
145
390
 
146
- 1. pnpm resolves the full dependency graph
147
- 2. `.pnpmfile.cjs` hook runs `afterAllResolved()` before downloads
148
- 3. The hook queries GitHub Advisory (and optionally NVD for severity enrichment)
149
- 4. Findings are deduplicated and checked against the severity policy
150
- 5. If any blocking vulnerabilities exist, pnpm aborts the install
391
+ ```
392
+ .pnpm-audit-cache/
393
+ ├── ab/
394
+ │ └── ab1234...def.json # Cached by SHA256 hash
395
+ ├── cd/
396
+ │ └── cd5678...ghi.json
397
+ └── ...
398
+ ```
151
399
 
152
- **Note:** The `.pnpmfile.cjs` file must be in your workspace root directory.
400
+ ### Dynamic TTL
401
+
402
+ Cache duration varies by severity to balance freshness and performance:
403
+
404
+ | Severity | TTL | Reason |
405
+ |----------|-----|--------|
406
+ | Critical | 15 min | Need fast response for active threats |
407
+ | High | 30 min | Important but less urgent |
408
+ | Medium | 1 hour | Standard caching |
409
+ | Low/Unknown | Config TTL | Use configured default |
153
410
 
154
411
  ## CI/CD Integration
155
412
 
@@ -181,61 +438,109 @@ The hook runs automatically during `pnpm install` and will fail the job if block
181
438
 
182
439
  The hook includes a bundled database of historical vulnerabilities (2020-2025) that enables faster audits and reduced API calls.
183
440
 
184
- ### How It Works
185
-
186
- - **Historical vulnerabilities** (before the cutoff date) are served from the bundled static database
187
- - **New vulnerabilities** (after the cutoff date) are fetched from live APIs
188
- - This hybrid approach provides offline capability for historical data while ensuring fresh data for recent disclosures
189
-
190
441
  ### Benefits
191
442
 
192
443
  - **Faster audits**: No API calls needed for known historical vulnerabilities
193
- - **Reduced API calls**: Only new vulnerabilities require network requests
194
- - **Offline capability**: Historical vulnerability checks work without internet access
195
- - **Rate limit friendly**: Minimizes API usage against GitHub and NVD
196
-
197
- ### Configuration
198
-
199
- Enable or disable the static baseline in `.pnpm-audit.yaml`:
200
-
201
- ```yaml
202
- staticBaseline:
203
- enabled: true
204
- cutoffDate: "2025-12-31"
205
- dataPath: "node_modules/pnpm-audit-hook/dist/static-db/data" # optional custom path
206
- ```
207
-
208
- - `enabled` - Whether to use the static database (default: `true`)
209
- - `cutoffDate` - Vulnerabilities published before this date use the static database (must be valid ISO format, not in future)
210
- - `dataPath` - Optional custom path to static data directory (default: bundled data)
444
+ - **Offline capability**: Historical vulnerability checks work without internet
445
+ - **Rate limit friendly**: Minimizes API usage
446
+ - **Reliable**: Not affected by API outages for historical data
211
447
 
212
448
  ### Updating the Database
213
449
 
214
- Update the bundled vulnerability database monthly to capture new disclosures:
215
-
216
450
  ```bash
217
- # Full rebuild of the vulnerability database
218
- pnpm run update-vuln-db
219
-
220
- # Incremental update (faster, adds only new vulnerabilities)
451
+ # Incremental update (recommended)
221
452
  pnpm run update-vuln-db:incremental
222
- ```
223
453
 
224
- After updating, rebuild and commit the changes:
454
+ # Full rebuild
455
+ pnpm run update-vuln-db
225
456
 
226
- ```bash
457
+ # Rebuild and commit
227
458
  pnpm run build
228
459
  git add src/static-db/data/ dist/static-db/data/
229
460
  git commit -m "chore: update vulnerability database"
230
461
  ```
231
462
 
232
- ### Update Workflow
463
+ ## Architecture
464
+
465
+ ```mermaid
466
+ classDiagram
467
+ class PnpmHook {
468
+ +afterAllResolved(lockfile, context)
469
+ }
470
+
471
+ class AuditEngine {
472
+ +runAudit(lockfile, runtime)
473
+ -extractPackages(lockfile)
474
+ -aggregateVulnerabilities(packages)
475
+ -evaluatePolicies(findings)
476
+ }
477
+
478
+ class VulnerabilitySource {
479
+ <<interface>>
480
+ +query(packageName, version)
481
+ }
482
+
483
+ class StaticDatabase {
484
+ +query(packageName, version)
485
+ -loadShard(packageName)
486
+ -bloomFilter
487
+ }
488
+
489
+ class GitHubAdvisory {
490
+ +query(packageName, version)
491
+ -fetchFromAPI()
492
+ -rateLimiter
493
+ }
494
+
495
+ class NVDEnricher {
496
+ +enrichSeverity(findings)
497
+ -fetchCVSS(cveId)
498
+ }
499
+
500
+ class PolicyEngine {
501
+ +evaluate(findings, config)
502
+ -checkAllowlist(finding)
503
+ -checkSeverity(finding)
504
+ }
505
+
506
+ class FileCache {
507
+ +get(key)
508
+ +set(key, value, ttl)
509
+ +prune()
510
+ }
511
+
512
+ PnpmHook --> AuditEngine
513
+ AuditEngine --> VulnerabilitySource
514
+ AuditEngine --> PolicyEngine
515
+ AuditEngine --> FileCache
516
+ VulnerabilitySource <|.. StaticDatabase
517
+ VulnerabilitySource <|.. GitHubAdvisory
518
+ GitHubAdvisory --> NVDEnricher
519
+ ```
520
+
521
+ ## Security Model
522
+
523
+ ### Fail-Closed Design
524
+
525
+ The hook uses a **fail-closed** security model:
526
+
527
+ | Condition | Behavior |
528
+ |-----------|----------|
529
+ | API failure | Block install (configurable) |
530
+ | Invalid allowlist entry | Entry ignored (treated as not allowed) |
531
+ | Expired allowlist | Entry ignored |
532
+ | Unknown severity | Treated as "warn" (configurable) |
533
+ | Invalid semver in vuln data | Treated as potentially affected |
534
+
535
+ ### Security Features
233
536
 
234
- 1. Run `pnpm run update-vuln-db:incremental` monthly
235
- 2. Optionally extend `cutoffDate` in your config to include newer static data
236
- 3. Commit the updated `data/` directory to your repository
537
+ - **Pre-download blocking**: Vulnerable code never reaches your machine
538
+ - **No credential storage**: API keys only from environment variables
539
+ - **Path traversal protection**: Validates all file paths
540
+ - **Symlink attack prevention**: Detects symlinks in cache
541
+ - **Atomic cache writes**: Prevents partial/corrupted cache files
237
542
 
238
- ## Local Development with pnpm
543
+ ## Local Development
239
544
 
240
545
  ### Setup
241
546
 
@@ -246,29 +551,7 @@ pnpm install
246
551
  pnpm run build
247
552
  ```
248
553
 
249
- ### Test in Another Project (pnpm link)
250
-
251
- ```bash
252
- # In pnpm-audit-hook directory
253
- pnpm link --global
254
-
255
- # In your target project
256
- pnpm link --global pnpm-audit-hook
257
-
258
- # Copy the hook file to your project root
259
- cp node_modules/pnpm-audit-hook/.pnpmfile.cjs .
260
-
261
- # Edit .pnpmfile.cjs to point to linked package
262
- # Change: path.join(__dirname, 'dist', 'index.js')
263
- # To: path.join(__dirname, 'node_modules', 'pnpm-audit-hook', 'dist', 'index.js')
264
-
265
- # Test it
266
- pnpm add lodash
267
- ```
268
-
269
- ### Test Directly in This Repo
270
-
271
- The `.pnpmfile.cjs` already points to `./dist`, so you can test directly:
554
+ ### Test Directly
272
555
 
273
556
  ```bash
274
557
  pnpm run build
@@ -276,33 +559,21 @@ pnpm add lodash # Safe package
276
559
  pnpm add event-stream@3.3.6 # Vulnerable - should be blocked
277
560
  ```
278
561
 
279
- ### Development Workflow
562
+ ### Run Tests
280
563
 
281
564
  ```bash
282
- # Make changes to src/
283
- pnpm run build
284
-
285
- # Run tests
286
565
  pnpm test
287
-
288
- # Test the hook manually
289
- pnpm add some-package
290
566
  ```
291
567
 
292
- ### Unlink After Testing
293
-
294
- ```bash
295
- # In your target project
296
- pnpm unlink pnpm-audit-hook
297
- rm .pnpmfile.cjs
568
+ ## Exit Codes
298
569
 
299
- # In pnpm-audit-hook directory
300
- pnpm unlink --global
301
- ```
570
+ | Code | Meaning |
571
+ |------|---------|
572
+ | 0 | Success - no blocking vulnerabilities |
573
+ | 1 | Blocked - critical/high vulnerabilities found |
574
+ | 2 | Warnings - medium/low vulnerabilities found |
575
+ | 3 | Source error - API failure (fail-closed) |
302
576
 
303
- ## Build
577
+ ## License
304
578
 
305
- ```bash
306
- pnpm install
307
- pnpm run build
308
- ```
579
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pnpm-audit-hook",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "pnpm hook that blocks vulnerable packages before download. Uses GitHub Advisory Database with offline static DB fallback.",
5
5
  "license": "MIT",
6
6
  "author": "asx8678",