verdaccio-security-filter 0.0.0 → 1.1.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 +719 -4
- package/build/index.d.ts +86 -0
- package/build/index.js +583 -0
- package/build/lib/cve-checker.d.ts +47 -0
- package/build/lib/cve-checker.js +286 -0
- package/build/lib/license-checker.d.ts +37 -0
- package/build/lib/license-checker.js +124 -0
- package/build/lib/logger.d.ts +42 -0
- package/build/lib/logger.js +95 -0
- package/build/lib/metrics.d.ts +54 -0
- package/build/lib/metrics.js +202 -0
- package/build/lib/package-age-checker.d.ts +49 -0
- package/build/lib/package-age-checker.js +138 -0
- package/build/lib/whitelist-checker.d.ts +48 -0
- package/build/lib/whitelist-checker.js +168 -0
- package/build/types.d.ts +119 -0
- package/build/types.js +2 -0
- package/package.json +61 -6
- package/index.js +0 -3
package/README.md
CHANGED
|
@@ -1,7 +1,722 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Verdaccio Security Filter Plugin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Advanced security filter plugin for Verdaccio with **dual-layer protection architecture** combining middleware interception and metadata filtering for comprehensive package security.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/verdaccio-security-filter)
|
|
6
|
+
[](https://www.npmjs.com/package/verdaccio-security-filter)
|
|
7
|
+
[](https://github.com/ponomarenko/verdaccio-security-filter/actions/workflows/ci.yml)
|
|
8
|
+
[](./tests)
|
|
9
|
+
[]()
|
|
10
|
+
[]()
|
|
11
|
+
[]()
|
|
6
12
|
|
|
7
|
-
|
|
13
|
+
## 🏗️ Dual-Layer Architecture
|
|
14
|
+
|
|
15
|
+
This plugin implements **two independent security layers** for complete protection:
|
|
16
|
+
|
|
17
|
+
### Layer 1: Middleware (Always Active)
|
|
18
|
+
- ✅ **Whitelist/Blacklist filtering** - Control allowed packages
|
|
19
|
+
- ✅ **Pattern-based blocking** - Block by regex patterns
|
|
20
|
+
- ✅ **Scope control** - Filter by npm scopes
|
|
21
|
+
- ✅ **Tarball interception** - Block downloads even if metadata cached
|
|
22
|
+
- ✅ **Version blocking** - Block specific versions/ranges
|
|
23
|
+
|
|
24
|
+
### Layer 2: Filter Metadata (Deep Inspection)
|
|
25
|
+
- ✅ **CVE vulnerability scanning** - OSV API integration
|
|
26
|
+
- ✅ **License compliance** - SPDX validation
|
|
27
|
+
- ✅ **Package age verification** - Block newly created packages
|
|
28
|
+
- ✅ **Full metadata access** - Deep package inspection
|
|
29
|
+
|
|
30
|
+
> **Why two layers?** Middleware catches everything at HTTP level, while filter_metadata provides deep inspection when metadata is available. See [DUAL-LAYER-ARCHITECTURE.md](./DUAL-LAYER-ARCHITECTURE.md) for details.
|
|
31
|
+
|
|
32
|
+
## 🚀 Features
|
|
33
|
+
|
|
34
|
+
### ✅ Implemented Features
|
|
35
|
+
|
|
36
|
+
#### 🔒 Version Management
|
|
37
|
+
- **Version Range Blocking** - Block vulnerable versions using semver ranges
|
|
38
|
+
- **Block Strategy**: Completely remove versions from registry
|
|
39
|
+
- **Fallback Strategy**: Transparently redirect to safe versions
|
|
40
|
+
- **Exact Version Blocking** - Block specific package@version combinations
|
|
41
|
+
- **Semver Support** - Full semver syntax (`^`, `~`, `>`, `>=`, `<`, `<=`, `x`, `*`)
|
|
42
|
+
|
|
43
|
+
#### 🛡️ CVE & Vulnerability Scanning
|
|
44
|
+
- **OSV Database Integration** - Automatic vulnerability scanning via [OSV API](https://osv.dev/)
|
|
45
|
+
- **Severity Filtering** - Filter by severity: `low`, `medium`, `high`, `critical`
|
|
46
|
+
- **Auto-Block Vulnerable Packages** - Automatically block packages with known CVEs
|
|
47
|
+
- **Caching System** - Configurable cache with update intervals
|
|
48
|
+
- **Multiple Database Support** - Ready for OSV, Snyk, GitHub Advisory
|
|
49
|
+
|
|
50
|
+
#### ⚖️ License Compliance
|
|
51
|
+
- **License Filtering** - Enforce license policies with allowed/blocked lists
|
|
52
|
+
- **SPDX Expression Support** - Parse complex license expressions (OR/AND operators)
|
|
53
|
+
- **Require License** - Option to block packages without license information
|
|
54
|
+
- **Pre-defined Lists** - Common open-source and copyleft license collections
|
|
55
|
+
|
|
56
|
+
#### 🔐 Access Control
|
|
57
|
+
- **Whitelist Mode** - Only explicitly approved packages allowed
|
|
58
|
+
- **Pattern-based Whitelisting** - Regex patterns for package approval
|
|
59
|
+
- **Version Constraints** - Lock approved packages to specific version ranges
|
|
60
|
+
- **Scope Control** - Whitelist/blacklist package scopes (@scope/package)
|
|
61
|
+
|
|
62
|
+
#### 📊 Monitoring & Observability
|
|
63
|
+
- **Enhanced Logging** - Configurable log levels (`debug`, `info`, `warn`, `error`)
|
|
64
|
+
- **Metrics Collection** - Track security events (blocks, fallbacks, CVEs, license violations)
|
|
65
|
+
- **Security Audit Trail** - Detailed logging of all security decisions
|
|
66
|
+
- **Customizable Output** - Log to stdout or file in JSON format
|
|
67
|
+
|
|
68
|
+
#### 🔍 Additional Security
|
|
69
|
+
- **Pattern-based Blocking** - Block suspicious packages by name patterns (regex)
|
|
70
|
+
- **Package Age Filtering** - Block packages or versions that are too new (protect against newly published malicious packages)
|
|
71
|
+
- **Minimum Package Age** - Require packages to exist for a minimum number of days
|
|
72
|
+
- **Minimum Version Age** - Require specific versions to exist for a minimum number of days
|
|
73
|
+
- **Warn-Only Mode** - Log warnings without blocking
|
|
74
|
+
- **Middleware Interception** - HTTP middleware that blocks tarball downloads for blocked packages
|
|
75
|
+
- Prevents blocked packages from being installed as dependencies
|
|
76
|
+
- Intercepts requests to `/:package/-/:filename.tgz` routes
|
|
77
|
+
- Returns 403 Forbidden with detailed error messages
|
|
78
|
+
- **Size Limits** - Enforce minimum and maximum package sizes
|
|
79
|
+
- **Metadata Validation** - Verify package integrity and detect dangerous characters
|
|
80
|
+
- **Checksum Enforcement** - Ensure package integrity
|
|
81
|
+
|
|
82
|
+
#### ⚙️ Reliability & Error Handling
|
|
83
|
+
- **Fail-Safe/Fail-Closed Configuration** - Choose error handling strategy
|
|
84
|
+
- **Fail-Open (Default)** - Allow packages on errors (availability priority)
|
|
85
|
+
- **Fail-Closed** - Block packages on errors (security priority)
|
|
86
|
+
- **Granular Control** - Different strategies for filter, CVE, and license checks
|
|
87
|
+
- **Retry Logic** - Automatic retry with exponential backoff for API calls
|
|
88
|
+
- 3 retries with increasing delays (1s, 2s, 4s)
|
|
89
|
+
- Rate limiting detection and handling
|
|
90
|
+
- Request timeout protection (10s)
|
|
91
|
+
- **Resilient CVE Scanning** - Production-ready vulnerability checking
|
|
92
|
+
- Network failure recovery
|
|
93
|
+
- API timeout protection
|
|
94
|
+
- Graceful degradation on errors
|
|
95
|
+
|
|
96
|
+
### 🔮 Planned Features (Roadmap)
|
|
97
|
+
|
|
98
|
+
#### Phase 3: Advanced Security
|
|
99
|
+
- [ ] **Dependency Depth Limiting** - Limit dependency tree depth and total count
|
|
100
|
+
- [ ] **Circular Dependency Detection** - Block packages with circular dependencies
|
|
101
|
+
- [ ] **Rate Limiting** - Detect and block suspicious download patterns
|
|
102
|
+
- [ ] **Typosquatting Detection** - AI-powered detection of similar package names
|
|
103
|
+
- [ ] **Package Signing Verification** - PGP signature validation
|
|
104
|
+
- [ ] **Custom Validation Scripts** - Execute custom security checks
|
|
105
|
+
|
|
106
|
+
#### Phase 4: Enterprise Features
|
|
107
|
+
- [ ] **Integration with Security Scanners** - npm audit, Snyk API, Sonatype
|
|
108
|
+
- [ ] **Webhook Notifications** - Real-time alerts for security events
|
|
109
|
+
- [ ] **Web Dashboard** - Visual interface for security analytics
|
|
110
|
+
- [ ] **Email/Slack Notifications** - Alert channels for critical events
|
|
111
|
+
- [ ] **Audit Reports** - Generate compliance reports (PDF, CSV, JSON)
|
|
112
|
+
- [ ] **Multi-Registry Support** - Fallback to other registries
|
|
113
|
+
- [ ] **ML-based Anomaly Detection** - Machine learning for threat detection
|
|
114
|
+
|
|
115
|
+
#### Phase 5: Developer Experience
|
|
116
|
+
- [ ] **Dry Run Mode** - Test rules without actually blocking
|
|
117
|
+
- [ ] **Auto-approve Criteria** - Automatic approval based on npm stats (downloads, stars)
|
|
118
|
+
- [ ] **CLI Tool** - Command-line interface for rule management
|
|
119
|
+
- [ ] **Visual Studio Code Extension** - IDE integration
|
|
120
|
+
- [ ] **GitHub Action** - CI/CD integration
|
|
121
|
+
|
|
122
|
+
## 📦 Installation
|
|
123
|
+
|
|
124
|
+
### Prerequisites
|
|
125
|
+
|
|
126
|
+
- Node.js >= 22.0.0
|
|
127
|
+
- Verdaccio >= 5.0.0
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npm install -g verdaccio
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Install Plugin
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Install from npm (when published)
|
|
137
|
+
npm install -g verdaccio-security-filter
|
|
138
|
+
|
|
139
|
+
# Or install locally for development
|
|
140
|
+
git clone https://github.com/ponomarenko/verdaccio-security-filter.git
|
|
141
|
+
cd verdaccio-security-filter
|
|
142
|
+
npm install
|
|
143
|
+
npm run build
|
|
144
|
+
npm link
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## 🔧 How It Works
|
|
148
|
+
|
|
149
|
+
This plugin implements **two layers of protection** to block malicious packages:
|
|
150
|
+
|
|
151
|
+
### Layer 1: Metadata Filtering (`filter_metadata`)
|
|
152
|
+
When a client requests package information (e.g., `npm info lodash`), the plugin:
|
|
153
|
+
1. Checks if the package is allowed (whitelist mode)
|
|
154
|
+
2. Validates against blocked patterns, scopes, and age requirements
|
|
155
|
+
3. **Throws HTTP 404 error** for completely blocked packages (patterns, scopes, whitelist violations)
|
|
156
|
+
4. Filters out specific blocked versions from the versions list for partial blocks
|
|
157
|
+
|
|
158
|
+
**Result**: Blocked packages return "404 Not Found" - as if they don't exist in the registry.
|
|
159
|
+
|
|
160
|
+
### Layer 2: Middleware Interception (`register_middlewares`)
|
|
161
|
+
When a client tries to download a tarball file (e.g., during `npm install`), the plugin:
|
|
162
|
+
1. Intercepts **all HTTP requests** early in the middleware chain
|
|
163
|
+
2. Extracts package name and version from the request URL
|
|
164
|
+
3. Applies all security checks (whitelist, patterns, scopes, blocked versions, range rules)
|
|
165
|
+
4. Returns **403 Forbidden** for blocked packages with detailed error message
|
|
166
|
+
|
|
167
|
+
**Result**: Even if metadata is cached, tarball downloads are blocked at the HTTP level.
|
|
168
|
+
|
|
169
|
+
### Why Both Layers?
|
|
170
|
+
|
|
171
|
+
- **Metadata filtering (404)** - Makes blocked packages invisible to npm/yarn
|
|
172
|
+
- **Middleware interception (403)** - Blocks tarball downloads even with cached metadata
|
|
173
|
+
- Together, they provide **complete protection** against blocked packages being installed in any way
|
|
174
|
+
|
|
175
|
+
Example flow when a blocked package is requested:
|
|
176
|
+
```
|
|
177
|
+
npm install hawk
|
|
178
|
+
→ GET /hawk (metadata request)
|
|
179
|
+
→ [Security Filter] Blocked hawk@* - Package is not in whitelist
|
|
180
|
+
→ HTTP 404 Not Found: Package blocked by security filter: Not in whitelist
|
|
181
|
+
→ npm ERR! 404 Not Found - GET http://localhost:4873/hawk
|
|
182
|
+
|
|
183
|
+
npm install (with hawk as dependency)
|
|
184
|
+
→ GET /hawk/-/hawk-9.0.1.tgz (tarball request)
|
|
185
|
+
→ [Middleware] Tarball request: hawk/hawk-9.0.1.tgz
|
|
186
|
+
→ [Security Filter] Blocked hawk@9.0.1 - Package is not in whitelist
|
|
187
|
+
→ HTTP 403 Forbidden: {"error": "Package blocked by security filter", "reason": "Package is not in whitelist"}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## ⚙️ Configuration
|
|
191
|
+
|
|
192
|
+
### Quick Start (Middleware Only)
|
|
193
|
+
|
|
194
|
+
Minimal configuration using only Layer 1 (Middleware):
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
middlewares:
|
|
198
|
+
security-filter:
|
|
199
|
+
enabled: true
|
|
200
|
+
mode: whitelist
|
|
201
|
+
whitelist:
|
|
202
|
+
packages:
|
|
203
|
+
- lodash
|
|
204
|
+
- express
|
|
205
|
+
patterns:
|
|
206
|
+
- "^@types/.*"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Full Protection (Dual-Layer)
|
|
210
|
+
|
|
211
|
+
**Recommended:** Use both layers for maximum security:
|
|
212
|
+
|
|
213
|
+
```yaml
|
|
214
|
+
# Enable filter_metadata (Layer 2)
|
|
215
|
+
packages:
|
|
216
|
+
'@*/*':
|
|
217
|
+
access: $all
|
|
218
|
+
publish: $authenticated
|
|
219
|
+
proxy: npmjs
|
|
220
|
+
storage: security-filter # Enable Layer 2!
|
|
221
|
+
|
|
222
|
+
'**':
|
|
223
|
+
access: $all
|
|
224
|
+
publish: $authenticated
|
|
225
|
+
proxy: npmjs
|
|
226
|
+
storage: security-filter # Enable Layer 2!
|
|
227
|
+
|
|
228
|
+
# Configure security filter
|
|
229
|
+
middlewares:
|
|
230
|
+
security-filter:
|
|
231
|
+
enabled: true
|
|
232
|
+
|
|
233
|
+
# Layer 1: Basic filtering (Middleware)
|
|
234
|
+
mode: whitelist
|
|
235
|
+
whitelist:
|
|
236
|
+
packages: [lodash, express]
|
|
237
|
+
patterns: ["^@types/.*"]
|
|
238
|
+
|
|
239
|
+
blockedVersions:
|
|
240
|
+
- "lodash@4.17.20"
|
|
241
|
+
|
|
242
|
+
# Layer 2: Deep inspection (filter_metadata)
|
|
243
|
+
cveCheck:
|
|
244
|
+
enabled: true
|
|
245
|
+
autoBlock: true
|
|
246
|
+
severity: [critical, high]
|
|
247
|
+
|
|
248
|
+
licenses:
|
|
249
|
+
allowed: [MIT, Apache-2.0, BSD-3-Clause]
|
|
250
|
+
|
|
251
|
+
packageAge:
|
|
252
|
+
enabled: true
|
|
253
|
+
minPackageAgeDays: 7
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Advanced Configuration with CVE Scanning
|
|
257
|
+
|
|
258
|
+
```yaml
|
|
259
|
+
# Layer 1: Metadata filtering
|
|
260
|
+
filters:
|
|
261
|
+
security-filter:
|
|
262
|
+
enabled: true
|
|
263
|
+
|
|
264
|
+
# CVE vulnerability scanning
|
|
265
|
+
cveCheck:
|
|
266
|
+
enabled: true
|
|
267
|
+
databases:
|
|
268
|
+
- osv
|
|
269
|
+
- github
|
|
270
|
+
severity:
|
|
271
|
+
- high
|
|
272
|
+
- critical
|
|
273
|
+
autoBlock: true
|
|
274
|
+
updateInterval: 24 # hours
|
|
275
|
+
cacheDir: ./.security-cache
|
|
276
|
+
|
|
277
|
+
# License compliance
|
|
278
|
+
licenses:
|
|
279
|
+
allowed:
|
|
280
|
+
- MIT
|
|
281
|
+
- Apache-2.0
|
|
282
|
+
- BSD-3-Clause
|
|
283
|
+
blocked:
|
|
284
|
+
- GPL-3.0
|
|
285
|
+
- AGPL-3.0
|
|
286
|
+
requireLicense: true
|
|
287
|
+
|
|
288
|
+
# Package age filtering
|
|
289
|
+
packageAge:
|
|
290
|
+
enabled: true
|
|
291
|
+
minPackageAgeDays: 7 # Packages must be at least 7 days old
|
|
292
|
+
minVersionAgeDays: 3 # Versions must be at least 3 days old
|
|
293
|
+
warnOnly: false # Block instead of just warning
|
|
294
|
+
|
|
295
|
+
# Version range rules
|
|
296
|
+
versionRangeRules:
|
|
297
|
+
- package: lodash
|
|
298
|
+
range: "<4.17.21"
|
|
299
|
+
strategy: fallback
|
|
300
|
+
fallbackVersion: "4.17.21"
|
|
301
|
+
reason: "CVE-2021-23337: Command injection"
|
|
302
|
+
|
|
303
|
+
- package: minimist
|
|
304
|
+
range: "<1.2.6"
|
|
305
|
+
strategy: block
|
|
306
|
+
reason: "CVE-2021-44906: Prototype pollution"
|
|
307
|
+
|
|
308
|
+
# Layer 2: Middleware interception
|
|
309
|
+
middlewares:
|
|
310
|
+
security-filter:
|
|
311
|
+
enabled: true
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Enterprise Whitelist Mode
|
|
315
|
+
|
|
316
|
+
```yaml
|
|
317
|
+
# Layer 1: Metadata filtering
|
|
318
|
+
filters:
|
|
319
|
+
security-filter:
|
|
320
|
+
enabled: true
|
|
321
|
+
|
|
322
|
+
# Only approved packages allowed
|
|
323
|
+
mode: whitelist
|
|
324
|
+
|
|
325
|
+
whitelist:
|
|
326
|
+
packages:
|
|
327
|
+
- lodash
|
|
328
|
+
- express
|
|
329
|
+
- react
|
|
330
|
+
patterns:
|
|
331
|
+
- "^@mycompany/.*"
|
|
332
|
+
- "^@types/.*"
|
|
333
|
+
versions:
|
|
334
|
+
lodash: "^4.17.21"
|
|
335
|
+
express: "^4.18.0"
|
|
336
|
+
|
|
337
|
+
# Enhanced logging
|
|
338
|
+
logger:
|
|
339
|
+
level: info
|
|
340
|
+
enabled: true
|
|
341
|
+
includeTimestamp: true
|
|
342
|
+
|
|
343
|
+
# Metrics for analytics
|
|
344
|
+
metrics:
|
|
345
|
+
enabled: true
|
|
346
|
+
output: file
|
|
347
|
+
filePath: ./security-metrics.json
|
|
348
|
+
|
|
349
|
+
# Layer 2: Middleware interception
|
|
350
|
+
middlewares:
|
|
351
|
+
security-filter:
|
|
352
|
+
enabled: true
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### High Security Configuration
|
|
356
|
+
|
|
357
|
+
```yaml
|
|
358
|
+
# Layer 1: Metadata filtering
|
|
359
|
+
filters:
|
|
360
|
+
security-filter:
|
|
361
|
+
enabled: true
|
|
362
|
+
mode: whitelist
|
|
363
|
+
|
|
364
|
+
whitelist:
|
|
365
|
+
packages:
|
|
366
|
+
- lodash
|
|
367
|
+
- axios
|
|
368
|
+
versions:
|
|
369
|
+
lodash: "4.17.21" # Lock to exact version
|
|
370
|
+
axios: "1.6.0"
|
|
371
|
+
|
|
372
|
+
cveCheck:
|
|
373
|
+
enabled: true
|
|
374
|
+
databases: [osv, github, snyk]
|
|
375
|
+
severity: [low, medium, high, critical] # Block ALL
|
|
376
|
+
autoBlock: true
|
|
377
|
+
updateInterval: 6 # Check every 6 hours
|
|
378
|
+
|
|
379
|
+
licenses:
|
|
380
|
+
allowed: [MIT, Apache-2.0, BSD-3-Clause]
|
|
381
|
+
blocked: [GPL-3.0, AGPL-3.0, LGPL-3.0]
|
|
382
|
+
requireLicense: true
|
|
383
|
+
|
|
384
|
+
minPackageSize: 10000 # 10KB minimum
|
|
385
|
+
maxPackageSize: 10485760 # 10MB maximum
|
|
386
|
+
|
|
387
|
+
logger:
|
|
388
|
+
level: debug # Log everything
|
|
389
|
+
enabled: true
|
|
390
|
+
includeTimestamp: true
|
|
391
|
+
|
|
392
|
+
metrics:
|
|
393
|
+
enabled: true
|
|
394
|
+
output: file
|
|
395
|
+
filePath: /var/log/verdaccio/security-metrics.jsonl
|
|
396
|
+
|
|
397
|
+
# Layer 2: Middleware interception
|
|
398
|
+
middlewares:
|
|
399
|
+
security-filter:
|
|
400
|
+
enabled: true
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## 📚 Configuration Reference
|
|
404
|
+
|
|
405
|
+
### Main Options
|
|
406
|
+
|
|
407
|
+
| Option | Type | Default | Description |
|
|
408
|
+
|--------|------|---------|-------------|
|
|
409
|
+
| `mode` | `string` | `blacklist` | Filter mode: `blacklist` or `whitelist` |
|
|
410
|
+
| `blockedVersions` | `string[]` | `[]` | List of `package@version` to block |
|
|
411
|
+
| `blockedPatterns` | `string[]` | `[]` | Regex patterns for package names |
|
|
412
|
+
| `allowedScopes` | `string[]` | `[]` | Allowed package scopes |
|
|
413
|
+
| `blockedScopes` | `string[]` | `[]` | Blocked package scopes |
|
|
414
|
+
| `minPackageSize` | `number` | `0` | Minimum package size in bytes |
|
|
415
|
+
| `maxPackageSize` | `number` | `104857600` | Maximum package size (100MB) |
|
|
416
|
+
| `enforceChecksum` | `boolean` | `true` | Enforce checksum validation |
|
|
417
|
+
|
|
418
|
+
### CVE Check Options
|
|
419
|
+
|
|
420
|
+
| Option | Type | Default | Description |
|
|
421
|
+
|--------|------|---------|-------------|
|
|
422
|
+
| `cveCheck.enabled` | `boolean` | `false` | Enable CVE scanning |
|
|
423
|
+
| `cveCheck.databases` | `string[]` | `['osv']` | Databases: `osv`, `snyk`, `github` |
|
|
424
|
+
| `cveCheck.severity` | `string[]` | `['high', 'critical']` | Severity levels to check |
|
|
425
|
+
| `cveCheck.autoBlock` | `boolean` | `false` | Auto-block vulnerable packages |
|
|
426
|
+
| `cveCheck.updateInterval` | `number` | `24` | Cache update interval (hours) |
|
|
427
|
+
| `cveCheck.cacheDir` | `string` | `./.security-cache` | Cache directory path |
|
|
428
|
+
|
|
429
|
+
### License Options
|
|
430
|
+
|
|
431
|
+
| Option | Type | Default | Description |
|
|
432
|
+
|--------|------|---------|-------------|
|
|
433
|
+
| `licenses.allowed` | `string[]` | `[]` | Allowed license list |
|
|
434
|
+
| `licenses.blocked` | `string[]` | `[]` | Blocked license list |
|
|
435
|
+
| `licenses.requireLicense` | `boolean` | `false` | Require license field |
|
|
436
|
+
|
|
437
|
+
### Whitelist Options
|
|
438
|
+
|
|
439
|
+
| Option | Type | Default | Description |
|
|
440
|
+
|--------|------|---------|-------------|
|
|
441
|
+
| `whitelist.packages` | `string[]` | `[]` | Approved package names |
|
|
442
|
+
| `whitelist.patterns` | `string[]` | `[]` | Regex patterns for approval |
|
|
443
|
+
| `whitelist.versions` | `object` | `{}` | Version constraints per package |
|
|
444
|
+
|
|
445
|
+
### Logger Options
|
|
446
|
+
|
|
447
|
+
| Option | Type | Default | Description |
|
|
448
|
+
|--------|------|---------|-------------|
|
|
449
|
+
| `logger.level` | `string` | `info` | Log level: `debug`, `info`, `warn`, `error` |
|
|
450
|
+
| `logger.enabled` | `boolean` | `true` | Enable logging |
|
|
451
|
+
| `logger.includeTimestamp` | `boolean` | `false` | Include timestamps in logs |
|
|
452
|
+
|
|
453
|
+
### Metrics Options
|
|
454
|
+
|
|
455
|
+
| Option | Type | Default | Description |
|
|
456
|
+
|--------|------|---------|-------------|
|
|
457
|
+
| `metrics.enabled` | `boolean` | `false` | Enable metrics collection |
|
|
458
|
+
| `metrics.output` | `string` | `stdout` | Output: `stdout` or `file` |
|
|
459
|
+
| `metrics.filePath` | `string` | `./security-metrics.json` | Metrics file path |
|
|
460
|
+
|
|
461
|
+
### Package Age Options
|
|
462
|
+
|
|
463
|
+
| Option | Type | Default | Description |
|
|
464
|
+
|--------|------|---------|-------------|
|
|
465
|
+
| `packageAge.enabled` | `boolean` | `false` | Enable package age filtering |
|
|
466
|
+
| `packageAge.minPackageAgeDays` | `number` | `0` | Minimum age for packages (days) |
|
|
467
|
+
| `packageAge.minVersionAgeDays` | `number` | `undefined` | Minimum age for versions (days) |
|
|
468
|
+
| `packageAge.warnOnly` | `boolean` | `false` | Only warn, don't block |
|
|
469
|
+
|
|
470
|
+
### Error Handling Options
|
|
471
|
+
|
|
472
|
+
| Option | Type | Default | Description |
|
|
473
|
+
|--------|------|---------|-------------|
|
|
474
|
+
| `errorHandling.onFilterError` | `'fail-open' \| 'fail-closed'` | `'fail-open'` | Strategy when filter errors occur |
|
|
475
|
+
| `errorHandling.onCveCheckError` | `'fail-open' \| 'fail-closed'` | `'fail-open'` | Strategy when CVE check fails |
|
|
476
|
+
| `errorHandling.onLicenseCheckError` | `'fail-open' \| 'fail-closed'` | `'fail-open'` | Strategy when license check fails |
|
|
477
|
+
|
|
478
|
+
**Error Handling Strategies:**
|
|
479
|
+
- **fail-open** (Default): Allow packages through on errors (prioritizes availability)
|
|
480
|
+
- **fail-closed**: Block packages on errors (prioritizes security)
|
|
481
|
+
|
|
482
|
+
**Example Configuration:**
|
|
483
|
+
```yaml
|
|
484
|
+
# Production: Security-first approach
|
|
485
|
+
errorHandling:
|
|
486
|
+
onFilterError: fail-closed
|
|
487
|
+
onCveCheckError: fail-closed
|
|
488
|
+
onLicenseCheckError: fail-closed
|
|
489
|
+
|
|
490
|
+
# Development: Availability-first approach
|
|
491
|
+
errorHandling:
|
|
492
|
+
onFilterError: fail-open
|
|
493
|
+
onCveCheckError: fail-open
|
|
494
|
+
onLicenseCheckError: fail-open
|
|
495
|
+
|
|
496
|
+
# Balanced: Block only on license failures
|
|
497
|
+
errorHandling:
|
|
498
|
+
onFilterError: fail-open
|
|
499
|
+
onCveCheckError: fail-open
|
|
500
|
+
onLicenseCheckError: fail-closed
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Version Range Rules
|
|
504
|
+
|
|
505
|
+
```typescript
|
|
506
|
+
{
|
|
507
|
+
package: string; // Package name
|
|
508
|
+
range: string; // Semver range
|
|
509
|
+
strategy: 'block' | 'fallback';
|
|
510
|
+
fallbackVersion?: string; // Required for fallback strategy
|
|
511
|
+
reason?: string; // Explanation for blocking
|
|
512
|
+
}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
## 📖 Examples
|
|
516
|
+
|
|
517
|
+
See the [examples](./examples) directory for complete configuration examples:
|
|
518
|
+
- [basic.yaml](./examples/basic.yaml) - Simple setup for small teams
|
|
519
|
+
- [enterprise.yaml](./examples/enterprise.yaml) - Comprehensive security setup
|
|
520
|
+
- [high-security.yaml](./examples/high-security.yaml) - Maximum security configuration
|
|
521
|
+
|
|
522
|
+
## 🧪 Testing
|
|
523
|
+
|
|
524
|
+
```bash
|
|
525
|
+
# Run all tests
|
|
526
|
+
npm test
|
|
527
|
+
|
|
528
|
+
# Run tests with coverage
|
|
529
|
+
npm test:coverage
|
|
530
|
+
|
|
531
|
+
# Run tests in watch mode
|
|
532
|
+
npm test:watch
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
**Test Results:**
|
|
536
|
+
- ✅ 80 tests passing
|
|
537
|
+
- ✅ 60%+ code coverage
|
|
538
|
+
- ✅ SecurityFilterPlugin: 21 tests
|
|
539
|
+
- ✅ PackageAgeChecker: 13 tests
|
|
540
|
+
- ✅ SecurityLogger: 16 tests
|
|
541
|
+
- ✅ LicenseChecker: 15 tests
|
|
542
|
+
- ✅ WhitelistChecker: 15 tests
|
|
543
|
+
|
|
544
|
+
## 🔧 Development
|
|
545
|
+
|
|
546
|
+
```bash
|
|
547
|
+
# Install dependencies
|
|
548
|
+
npm install
|
|
549
|
+
|
|
550
|
+
# Build
|
|
551
|
+
npm run build
|
|
552
|
+
|
|
553
|
+
# Lint
|
|
554
|
+
npm run lint
|
|
555
|
+
|
|
556
|
+
# Watch mode for development
|
|
557
|
+
npm run build -- --watch
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
## 📊 Metrics & Monitoring
|
|
561
|
+
|
|
562
|
+
When metrics are enabled, the plugin tracks:
|
|
563
|
+
|
|
564
|
+
- `block` - Packages blocked by version/pattern/scope rules
|
|
565
|
+
- `fallback` - Versions redirected to safe alternatives
|
|
566
|
+
- `publish_rejected` - Publish attempts rejected
|
|
567
|
+
- `cve_detected` - CVE vulnerabilities found
|
|
568
|
+
- `license_blocked` - Packages blocked by license rules
|
|
569
|
+
- `package_too_new` - Packages/versions blocked due to age restrictions
|
|
570
|
+
|
|
571
|
+
Example metrics output:
|
|
572
|
+
```json
|
|
573
|
+
{
|
|
574
|
+
"timestamp": "2025-01-15T10:30:00.000Z",
|
|
575
|
+
"event": "cve_detected",
|
|
576
|
+
"packageName": "lodash",
|
|
577
|
+
"version": "4.17.20",
|
|
578
|
+
"reason": "CVE-2021-23337 (high)",
|
|
579
|
+
"metadata": {
|
|
580
|
+
"cveId": "CVE-2021-23337",
|
|
581
|
+
"severity": "high"
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
## 🛠️ Use Cases
|
|
587
|
+
|
|
588
|
+
### 1. Block Known Vulnerabilities
|
|
589
|
+
|
|
590
|
+
```yaml
|
|
591
|
+
versionRangeRules:
|
|
592
|
+
- package: lodash
|
|
593
|
+
range: ">=4.17.0 <4.17.21"
|
|
594
|
+
strategy: block
|
|
595
|
+
reason: "CVE-2021-23337: Command injection vulnerability"
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
### 2. Transparent Security Patches (Fallback)
|
|
599
|
+
|
|
600
|
+
```yaml
|
|
601
|
+
versionRangeRules:
|
|
602
|
+
- package: axios
|
|
603
|
+
range: "0.21.1"
|
|
604
|
+
strategy: fallback
|
|
605
|
+
fallbackVersion: "0.21.4"
|
|
606
|
+
reason: "SSRF vulnerability fix"
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
### 3. Enforce Corporate License Policy
|
|
610
|
+
|
|
611
|
+
```yaml
|
|
612
|
+
licenses:
|
|
613
|
+
allowed:
|
|
614
|
+
- MIT
|
|
615
|
+
- Apache-2.0
|
|
616
|
+
- BSD-3-Clause
|
|
617
|
+
blocked:
|
|
618
|
+
- GPL-3.0
|
|
619
|
+
- AGPL-3.0
|
|
620
|
+
requireLicense: true
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
### 4. Whitelist Only Approved Packages
|
|
624
|
+
|
|
625
|
+
```yaml
|
|
626
|
+
mode: whitelist
|
|
627
|
+
whitelist:
|
|
628
|
+
packages:
|
|
629
|
+
- lodash
|
|
630
|
+
- express
|
|
631
|
+
patterns:
|
|
632
|
+
- "^@mycompany/.*"
|
|
633
|
+
versions:
|
|
634
|
+
lodash: "^4.17.21"
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### 5. Automatic CVE Scanning
|
|
638
|
+
|
|
639
|
+
```yaml
|
|
640
|
+
cveCheck:
|
|
641
|
+
enabled: true
|
|
642
|
+
databases: [osv, github]
|
|
643
|
+
severity: [high, critical]
|
|
644
|
+
autoBlock: true
|
|
645
|
+
updateInterval: 12
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
### 6. Block Recently Published Packages
|
|
649
|
+
|
|
650
|
+
```yaml
|
|
651
|
+
# Protect against newly published malicious packages
|
|
652
|
+
packageAge:
|
|
653
|
+
enabled: true
|
|
654
|
+
minPackageAgeDays: 7 # Package must exist for 7 days
|
|
655
|
+
minVersionAgeDays: 3 # Version must exist for 3 days
|
|
656
|
+
warnOnly: false # Block, don't just warn
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
## 🔐 Security Best Practices
|
|
660
|
+
|
|
661
|
+
1. **Enable CVE Scanning** - Automatically detect and block vulnerable packages
|
|
662
|
+
2. **Use Whitelist Mode** - For maximum security in sensitive environments
|
|
663
|
+
3. **Enforce License Compliance** - Prevent legal issues with license filtering
|
|
664
|
+
4. **Enable Package Age Filtering** - Block newly published packages to prevent supply chain attacks
|
|
665
|
+
5. **Enable Metrics** - Track security events for audit and compliance
|
|
666
|
+
6. **Regular Updates** - Keep the plugin and CVE database cache updated
|
|
667
|
+
7. **Test Rules** - Use dry run mode (planned) before applying strict rules
|
|
668
|
+
8. **Monitor Logs** - Review security logs regularly for suspicious activity
|
|
669
|
+
|
|
670
|
+
## 🐛 Troubleshooting
|
|
671
|
+
|
|
672
|
+
### Plugin not loading
|
|
673
|
+
- Verify Verdaccio version >= 5.0.0
|
|
674
|
+
- Check plugin is listed in `config.yaml` under `filters`
|
|
675
|
+
- Ensure plugin is installed globally or linked correctly
|
|
676
|
+
|
|
677
|
+
### CVE scanning not working
|
|
678
|
+
- Check internet connectivity to OSV API (https://api.osv.dev)
|
|
679
|
+
- Verify `cveCheck.enabled` is `true`
|
|
680
|
+
- Check cache directory permissions
|
|
681
|
+
- Review logs for API errors
|
|
682
|
+
|
|
683
|
+
### Tests failing
|
|
684
|
+
- Ensure Node.js >= 22.0.0
|
|
685
|
+
- Run `npm install` to update dependencies
|
|
686
|
+
- Clear Jest cache: `npx jest --clearCache`
|
|
687
|
+
|
|
688
|
+
### Package blocked unexpectedly
|
|
689
|
+
- Check logs for the reason: `logger.level: debug`
|
|
690
|
+
- Review all active rules (patterns, scopes, CVE, license)
|
|
691
|
+
- In whitelist mode, ensure package is explicitly approved
|
|
692
|
+
|
|
693
|
+
## 📄 License
|
|
694
|
+
|
|
695
|
+
MIT © [Vitaliy Ponomarenko](https://github.com/ponomarenko)
|
|
696
|
+
|
|
697
|
+
## 🤝 Contributing
|
|
698
|
+
|
|
699
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
700
|
+
|
|
701
|
+
1. Fork the repository
|
|
702
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
703
|
+
3. Run tests (`npm test`)
|
|
704
|
+
4. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
705
|
+
5. Push to the branch (`git push origin feature/amazing-feature`)
|
|
706
|
+
6. Open a Pull Request
|
|
707
|
+
|
|
708
|
+
## 📞 Support
|
|
709
|
+
|
|
710
|
+
- **Issues**: [GitHub Issues](https://github.com/ponomarenko/verdaccio-security-filter/issues)
|
|
711
|
+
- **Documentation**: [README](./README.md)
|
|
712
|
+
- **Examples**: [Configuration Examples](./examples)
|
|
713
|
+
|
|
714
|
+
## 🙏 Acknowledgments
|
|
715
|
+
|
|
716
|
+
- [Verdaccio](https://verdaccio.org/) - The awesome private npm registry
|
|
717
|
+
- [OSV](https://osv.dev/) - Open Source Vulnerabilities database
|
|
718
|
+
- All contributors and users of this plugin
|
|
719
|
+
|
|
720
|
+
---
|
|
721
|
+
|
|
722
|
+
**Made with ❤️ for the npm security community**
|