muaddib-scanner 2.6.2 → 2.6.4

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 CHANGED
@@ -17,7 +17,7 @@
17
17
  <a href="#usage">Usage</a> |
18
18
  <a href="#features">Features</a> |
19
19
  <a href="#vs-code">VS Code</a> |
20
- <a href="#ci-cd">CI/CD</a>
20
+ <a href="#cicd">CI/CD</a>
21
21
  </p>
22
22
 
23
23
  <p align="center">
@@ -30,21 +30,19 @@
30
30
 
31
31
  npm and PyPI supply-chain attacks are exploding. Shai-Hulud compromised 25K+ repos in 2025. Existing tools detect threats but don't help you respond.
32
32
 
33
- MUAD'DIB combines static analysis + **deobfuscation engine** (v2.2.5) + **inter-module dataflow** (v2.2.6) + **per-file max scoring** (v2.2.11) + dynamic analysis (Docker sandbox with **monkey-patching preload** for time-bomb detection, v2.4.9) + **behavioral anomaly detection** (v2.0) + **ground truth validation** (v2.1) + **security audit** (41 issues remediated, v2.5.0–v2.5.6) + **audit hardening** (v2.5.13–v2.5.14) + **FP reduction P5/P6** (v2.5.15–v2.5.16) to detect threats AND guide your response — even before they appear in any IOC database.
33
+ MUAD'DIB combines **14 parallel scanners** (129 detection rules), a **deobfuscation engine**, **inter-module dataflow analysis**, **per-file max scoring**, Docker sandbox with **monkey-patching preload** for time-bomb detection, **behavioral anomaly detection**, and **ground truth validation** to detect threats AND guide your response — even before they appear in any IOC database.
34
34
 
35
35
  ---
36
36
 
37
37
  ## Positioning
38
38
 
39
- MUAD'DIB is an educational tool and a free first line of defense. It detects **known** npm and PyPI threats (225,000+ IOCs) and basic suspicious patterns.
39
+ MUAD'DIB is an educational tool and a free first line of defense. It detects **known** npm and PyPI threats (225,000+ IOCs) and suspicious behavioral patterns.
40
40
 
41
41
  **For enterprise protection**, use:
42
42
  - [Socket.dev](https://socket.dev) - ML behavioral analysis, cloud sandboxing
43
43
  - [Snyk](https://snyk.io) - Massive vulnerability database, CI/CD integrations
44
44
  - [Opengrep](https://opengrep.dev) - Advanced dataflow analysis, Semgrep rules
45
45
 
46
- MUAD'DIB does not replace these tools. It complements them for devs who want a quick, free check before installing an unknown package.
47
-
48
46
  ---
49
47
 
50
48
  ## Installation
@@ -83,14 +81,11 @@ Scans both npm (package.json, node_modules) and Python (requirements.txt, setup.
83
81
  muaddib
84
82
  ```
85
83
 
86
- Launches an interactive menu to guide you through all features.
87
-
88
84
  ### Safe install
89
85
 
90
86
  ```bash
91
87
  muaddib install <package>
92
88
  muaddib install lodash axios --save-dev
93
- muaddib i express -g
94
89
  muaddib install suspicious-pkg --force # Force install despite threats
95
90
  ```
96
91
 
@@ -104,17 +99,13 @@ Each scan displays a 0-100 risk score:
104
99
  [SCORE] 58/100 [***********---------] HIGH
105
100
  ```
106
101
 
107
- ### Explain mode (full details)
102
+ ### Explain mode
108
103
 
109
104
  ```bash
110
105
  muaddib scan . --explain
111
106
  ```
112
107
 
113
- Shows for each detection:
114
- - Rule ID
115
- - MITRE ATT&CK technique
116
- - References (articles, CVEs)
117
- - Response playbook
108
+ Shows rule ID, MITRE ATT&CK technique, references, and response playbook for each detection.
118
109
 
119
110
  ### Export
120
111
 
@@ -129,7 +120,6 @@ muaddib scan . --sarif results.sarif # SARIF (GitHub Security)
129
120
  ```bash
130
121
  muaddib scan . --fail-on critical # Fail only on CRITICAL
131
122
  muaddib scan . --fail-on high # Fail on HIGH and CRITICAL (default)
132
- muaddib scan . --fail-on medium # Fail on MEDIUM, HIGH, CRITICAL
133
123
  ```
134
124
 
135
125
  ### Paranoid mode
@@ -138,431 +128,86 @@ muaddib scan . --fail-on medium # Fail on MEDIUM, HIGH, CRITICAL
138
128
  muaddib scan . --paranoid
139
129
  ```
140
130
 
141
- Ultra-strict detection with lower tolerance. Useful for critical projects. Detects any network access, subprocess execution, dynamic code evaluation, and sensitive file access.
131
+ Ultra-strict detection with lower tolerance. Detects any network access, subprocess execution, dynamic code evaluation, and sensitive file access.
142
132
 
143
- ### Discord/Slack webhook
133
+ ### Webhook alerts
144
134
 
145
135
  ```bash
146
136
  muaddib scan . --webhook "https://discord.com/api/webhooks/..."
147
137
  ```
148
138
 
149
- Sends an alert with score and threats to Discord or Slack. Strict filtering (v2.1.2): alerts are only sent for IOC matches, sandbox-confirmed threats, or canary token exfiltration — reducing noise from heuristic-only detections.
150
-
151
- ### Real-time monitoring
152
-
153
- ```bash
154
- muaddib watch .
155
- ```
156
-
157
- ### Daemon mode
158
-
159
- ```bash
160
- muaddib daemon
161
- muaddib daemon --webhook "https://discord.com/api/webhooks/..."
162
- ```
163
-
164
- Automatically monitors all `npm install` commands and scans new packages.
165
-
166
- ### Update IOCs (fast, ~5 seconds)
167
-
168
- ```bash
169
- muaddib update
170
- ```
171
-
172
- Loads the 225,000+ IOCs shipped in the package, merges YAML IOCs and additional GitHub sources (GenSecAI, DataDog). Run this after `npm install` for an instant IOC refresh.
139
+ Strict filtering (v2.1.2): alerts only for IOC matches, sandbox-confirmed threats, or canary token exfiltration.
173
140
 
174
- ### Scrape IOCs (full, ~5 minutes)
141
+ ### Behavioral anomaly detection (v2.0)
175
142
 
176
143
  ```bash
177
- muaddib scrape
144
+ muaddib scan . --temporal-full # All 4 temporal features
145
+ muaddib scan . --temporal # Sudden lifecycle script detection
146
+ muaddib scan . --temporal-ast # AST diff between versions
147
+ muaddib scan . --temporal-publish # Publish frequency anomaly
148
+ muaddib scan . --temporal-maintainer # Maintainer change detection
178
149
  ```
179
150
 
180
- Full refresh from all primary sources. Downloads OSV bulk dumps for npm and PyPI (~100-200MB), OSSF, and all other sources. Run this when you want the absolute latest data.
181
-
182
- Sources:
183
- - **OSV.dev npm dump** - Bulk download of all MAL-* entries
184
- - **OSV.dev PyPI dump** - Bulk download of all PyPI MAL-* entries
185
- - **GenSecAI Shai-Hulud 2.0 Detector** - Consolidated list of 700+ Shai-Hulud packages
186
- - **DataDog Security Labs** - Consolidated IOCs from multiple vendors
187
- - **OSSF Malicious Packages** - OpenSSF database (8000+ reports via OSV.dev)
188
- - **GitHub Advisory Database** - Malware-tagged advisories
189
- - **Snyk Known Malware** - Historical malware packages
190
- - **Static IOCs** - Socket.dev, Phylum, npm-removed packages
151
+ Detects supply-chain attacks **before** they appear in IOC databases by analyzing changes between package versions. See [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md) for details.
191
152
 
192
- ### Docker Sandbox
153
+ ### Docker sandbox
193
154
 
194
155
  ```bash
195
156
  muaddib sandbox <package-name>
196
157
  muaddib sandbox <package-name> --strict
197
158
  ```
198
159
 
199
- Dynamic analysis: installs the package in an isolated Docker container and monitors runtime behavior via strace, tcpdump, and filesystem diffing.
200
-
201
- Multi-layer monitoring:
202
- - **System tracing** (strace): file access, process spawns, syscall monitoring
203
- - **Network capture** (tcpdump): DNS resolutions with resolved IPs, HTTP requests (method, host, path, body), TLS SNI detection
204
- - **Filesystem diff**: snapshot before/after install, detects files created in suspicious locations
205
- - **Data exfiltration detection**: 16 sensitive patterns (tokens, credentials, SSH keys, private keys, .env)
206
- - **CI-aware environment** (v2.1.2): simulates CI environments (GITHUB_ACTIONS, GITLAB_CI, TRAVIS, CIRCLECI, JENKINS) to trigger CI-aware malware that would otherwise stay dormant
207
- - **Enriched canary tokens** (v2.1.2): 6 honeypot credentials injected as env vars (GITHUB_TOKEN, NPM_TOKEN, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, SLACK_WEBHOOK_URL, DISCORD_WEBHOOK_URL). If exfiltrated via network, DNS, or filesystem, triggers CRITICAL alert with +50 score
208
- - **Monkey-patching preload** (v2.4.9): Runtime instrumentation via `NODE_OPTIONS=--require /opt/preload.js`. Patches time APIs (Date.now, setTimeout→0, setInterval→immediate), intercepts network/filesystem/process/env calls. Multi-run mode at [0h, 72h, 7d] offsets to detect time-bomb malware (MITRE T1497.003)
209
- - **Scoring engine**: 0-100 risk score based on behavioral severity
210
-
211
- Use `--strict` to block all non-essential outbound network traffic via iptables.
212
-
213
- Requires Docker Desktop installed.
214
-
215
- ```bash
216
- muaddib sandbox lodash # Safe package
217
- muaddib sandbox suspicious-pkg # Analyze unknown package
218
- ```
219
-
220
- ### Sandbox network report
160
+ Dynamic analysis in an isolated Docker container: strace, tcpdump, filesystem diff, canary tokens, CI-aware environment, and monkey-patching preload for time-bomb detection (multi-run at [0h, 72h, 7d] offsets).
221
161
 
222
- ```bash
223
- muaddib sandbox-report <package-name>
224
- muaddib sandbox-report <package-name> --strict
225
- ```
226
-
227
- Same as `sandbox` but displays a detailed network report: DNS resolutions, HTTP requests, TLS connections, blocked connections (strict mode), and data exfiltration alerts.
228
-
229
- ### Diff (compare versions)
230
-
231
- ```bash
232
- muaddib diff <ref> [path]
233
- ```
234
-
235
- Compare threats between the current version and a previous commit/tag. Shows only **NEW** threats introduced since the reference point.
236
-
237
- ```bash
238
- muaddib diff HEAD~1 # Compare with previous commit
239
- muaddib diff v1.2.0 # Compare with tag
240
- muaddib diff main # Compare with branch
241
- muaddib diff abc1234 # Compare with specific commit
242
- ```
243
-
244
- Example output:
245
- ```
246
- [MUADDIB DIFF] Comparing abc1234 -> def5678
247
-
248
- Risk Score: 25 -> 45 (+20 worse)
249
- Threats: 3 -> 5
250
-
251
- NEW threats: 2
252
- REMOVED threats: 0
253
- Unchanged: 3
254
-
255
- NEW THREATS (introduced since v1.2.0)
256
- ------------------------------------
257
- 1. [HIGH] suspicious_dependency
258
- Known malicious package detected
259
- File: package.json
260
- ```
261
-
262
- Use in CI to only fail on **new** threats, not existing technical debt:
263
- ```yaml
264
- - run: muaddib diff ${{ github.event.pull_request.base.sha }} --fail-on high
265
- ```
266
-
267
- ### Pre-commit hooks
162
+ ### Other commands
268
163
 
269
164
  ```bash
270
- muaddib init-hooks [options]
165
+ muaddib watch . # Real-time monitoring
166
+ muaddib daemon # Daemon mode (auto-scan npm install)
167
+ muaddib update # Update IOCs (fast, ~5s)
168
+ muaddib scrape # Full IOC refresh (~5min)
169
+ muaddib diff HEAD~1 # Compare threats with previous commit
170
+ muaddib init-hooks # Pre-commit hooks (husky/pre-commit/git)
171
+ muaddib scan . --breakdown # Explainable score decomposition
172
+ muaddib replay # Ground truth validation (46/49 TPR)
271
173
  ```
272
174
 
273
- Automatically scan before each commit. Supports multiple hook systems:
274
-
275
- ```bash
276
- muaddib init-hooks # Auto-detect (husky/pre-commit/git)
277
- muaddib init-hooks --type husky # Force husky
278
- muaddib init-hooks --type pre-commit # Force pre-commit framework
279
- muaddib init-hooks --type git # Force native git hooks
280
- muaddib init-hooks --mode diff # Only block NEW threats
281
- ```
282
-
283
- #### With pre-commit framework
284
-
285
- Add to `.pre-commit-config.yaml`:
286
- ```yaml
287
- repos:
288
- - repo: https://github.com/DNSZLSK/muad-dib
289
- rev: v2.5.17
290
- hooks:
291
- - id: muaddib-scan # Scan all threats
292
- # - id: muaddib-diff # Or: only new threats
293
- # - id: muaddib-paranoid # Or: ultra-strict mode
294
- ```
295
-
296
- #### With husky
297
-
298
- ```bash
299
- npx husky add .husky/pre-commit "npx muaddib scan . --fail-on high"
300
- # Or for diff mode:
301
- npx husky add .husky/pre-commit "npx muaddib diff HEAD --fail-on high"
302
- ```
303
-
304
- #### Remove hooks
305
-
306
- ```bash
307
- muaddib remove-hooks [path]
308
- ```
309
-
310
- Removes all MUAD'DIB hooks (husky and git native).
311
-
312
- #### Native git hooks
313
-
314
- ```bash
315
- muaddib init-hooks --type git
316
- # Creates .git/hooks/pre-commit
317
- ```
318
-
319
- ### Zero-Day Monitor
320
-
321
- MUAD'DIB continuously monitors npm and PyPI registries for new packages in real-time, scanning each one automatically with Docker sandbox analysis and webhook alerting. This runs internally on our infrastructure — detected threats feed into the IOC database and threat feed API.
322
-
323
- ### Score breakdown
324
-
325
- ```bash
326
- muaddib scan . --breakdown
327
- ```
328
-
329
- Shows explainable score breakdown: how each finding contributes to the final risk score, with per-rule weights and severity multipliers.
330
-
331
- ### Ground truth replay
332
-
333
- ```bash
334
- muaddib replay
335
- muaddib ground-truth
336
- ```
337
-
338
- Replay real-world supply-chain attacks against the scanner to validate detection coverage. Current results: **46/49 detected (93.9% TPR)** from 51 samples (49 active).
339
-
340
- 4 out-of-scope misses: lottie-player, polyfill-io, trojanized-jquery (browser-only DOM attacks), websocket-rat (FP-risky pattern).
341
-
342
- ### Version check
343
-
344
- MUAD'DIB automatically checks for new versions on startup and notifies you if an update is available.
345
-
346
175
  ---
347
176
 
348
177
  ## Features
349
178
 
350
- ### Python / PyPI support
351
-
352
- MUAD'DIB automatically detects and scans Python projects:
353
-
354
- - **requirements.txt** - All formats including `-r` recursive includes, extras, environment markers
355
- - **setup.py** - Extracts `install_requires` and `setup_requires`
356
- - **pyproject.toml** - PEP 621 dependencies and Poetry dependencies
357
-
358
- Python packages are checked against 14,000+ known malicious PyPI packages (from OSV.dev) and tested for typosquatting against popular PyPI packages (requests, numpy, flask, django, pandas, etc.) using PEP 503 name normalization.
359
-
360
- ```
361
- [PYTHON] Detected Python project (3 dependency files)
362
- requirements.txt: 12 packages
363
- setup.py: 3 packages
364
- pyproject.toml: 8 packages
365
-
366
- [CRITICAL] PyPI IOC match: malicious-pkg (all versions)
367
- [HIGH] PyPI typosquat: "reqeusts" looks like "requests"
368
- ```
369
-
370
- ### Typosquatting detection
371
-
372
- MUAD'DIB detects packages with names similar to popular packages (npm and PyPI):
373
-
374
- ```
375
- [HIGH] Package "lodahs" looks like "lodash" (swapped_chars). Possible typosquatting.
376
- ```
377
-
378
- ### Dataflow analysis
379
-
380
- Detects when code reads credentials AND sends them over the network:
381
-
382
- ```
383
- [CRITICAL] Suspicious flow: credential read (readFileSync, GITHUB_TOKEN) + network send (fetch)
384
- ```
385
-
386
- ### GitHub Actions scanning
387
-
388
- Detects malicious patterns in `.github/workflows/` YAML files, including Shai-Hulud 2.0 backdoor indicators.
389
-
390
- ### Detected attacks
391
-
392
- | Campaign | Packages | Status |
393
- |----------|----------|--------|
394
- | Shai-Hulud v1 (Sept 2025) | @ctrl/tinycolor, ng2-file-upload | Detected |
395
- | Shai-Hulud v2 (Nov 2025) | @asyncapi/specs, posthog-node, kill-port | Detected |
396
- | Shai-Hulud v3 (Dec 2025) | @vietmoney/react-big-calendar | Detected |
397
- | event-stream (2018) | flatmap-stream, event-stream | Detected |
398
- | eslint-scope (2018) | eslint-scope | Detected |
399
- | Protestware | node-ipc, colors, faker | Detected |
400
- | Typosquats | crossenv, mongose, babelcli | Detected |
401
-
402
- ### Detected techniques
403
-
404
- | Technique | MITRE | Detection |
405
- |-----------|-------|-----------|
406
- | Credential theft (.npmrc, .ssh) | T1552.001 | AST |
407
- | Env var exfiltration | T1552.001 | AST |
408
- | Remote code execution | T1105 | Pattern |
409
- | Reverse shell | T1059.004 | Pattern |
410
- | Dead man's switch | T1485 | Pattern |
411
- | Obfuscated code | T1027 | Heuristics |
412
- | JS obfuscation patterns | T1027.002 | Pattern detection |
413
- | Shannon entropy (strings) | T1027 | Entropy calculation |
414
- | Typosquatting (npm + PyPI) | T1195.002 | Levenshtein |
415
- | Supply chain compromise | T1195.002 | IOC matching |
416
- | PyPI malicious package | T1195.002 | IOC matching |
417
- | Sandbox dynamic analysis | Multiple | Docker + strace + tcpdump |
418
- | Sudden lifecycle script addition | T1195.002 | Temporal analysis |
419
- | Dangerous API injection between versions | T1195.002 | Temporal AST diff |
420
- | Publish frequency anomaly | T1195.002 | Registry metadata |
421
- | Maintainer/publisher change | T1195.002 | Registry metadata |
422
- | Canary token exfiltration | T1552.001 | Sandbox honey tokens |
423
- | AI agent weaponization | T1059.004 | AST (s1ngularity/Nx flags) |
424
- | AI config prompt injection | T1059.004 | File scanning (.cursorrules, CLAUDE.md) |
425
- | Credential CLI theft (gh, gcloud, aws) | T1552.001 | AST |
426
- | Binary dropper (chmod + exec /tmp) | T1105 | AST |
427
- | Prototype hooking (fetch, XMLHttpRequest) | T1557 | AST |
428
- | Workflow injection (.github/workflows) | T1195.002 | AST |
429
- | Crypto wallet harvesting | T1005 | Dataflow |
430
- | Require cache poisoning | T1574.001 | AST |
431
- | Staged eval decode (eval+atob/Buffer) | T1140 | AST |
432
- | Deobfuscation (string concat, charcode, base64, hex) | T1140 | AST pre-processing |
433
- | Cross-file dataflow (inter-module exfiltration) | T1041 | Module graph |
434
-
435
- ---
436
-
437
- ## Supply Chain Anomaly Detection (v2.0)
438
-
439
- MUAD'DIB 2.0 introduces a paradigm shift: from **IOC-based detection** (reactive, requires known threats) to **behavioral anomaly detection** (proactive, detects unknown threats by spotting suspicious changes).
440
-
441
- Traditional supply-chain scanners rely on blocklists of known malicious packages. The problem: they can only detect threats AFTER they've been identified and reported. Attacks like **ua-parser-js** (2021), **event-stream** (2018), and **Shai-Hulud** (2025) went undetected for hours or days because no IOC existed yet.
442
-
443
- MUAD'DIB 2.0 adds 5 behavioral detection features that can catch these attacks **before** they appear in any IOC database, by analyzing what changed between package versions.
444
-
445
- ### New features
446
-
447
- #### 1. Sudden Lifecycle Script Detection (`--temporal`)
448
-
449
- Detects when `preinstall`, `install`, or `postinstall` scripts suddenly appear in a new version of a package that never had them before. This is the #1 attack vector for supply-chain attacks.
450
-
451
- ```bash
452
- muaddib scan . --temporal
453
- ```
454
-
455
- #### 2. Temporal AST Diff (`--temporal-ast`)
456
-
457
- Downloads the two latest versions of each dependency and compares their AST (Abstract Syntax Tree) to detect newly added dangerous APIs: `child_process`, `eval`, `Function`, `net.connect`, `process.env`, `fetch`, etc.
458
-
459
- ```bash
460
- muaddib scan . --temporal-ast
461
- ```
462
-
463
- #### 3. Publish Frequency Anomaly (`--temporal-publish`)
464
-
465
- Detects abnormal publishing patterns: burst of versions in 24h, dormant package suddenly updated after 6+ months, rapid version succession (multiple releases in under 1h).
466
-
467
- ```bash
468
- muaddib scan . --temporal-publish
469
- ```
470
-
471
- #### 4. Maintainer Change Detection (`--temporal-maintainer`)
472
-
473
- Detects changes in package maintainers between versions: new maintainer added, sole maintainer replaced (event-stream pattern), suspicious maintainer names, new publisher.
474
-
475
- ```bash
476
- muaddib scan . --temporal-maintainer
477
- ```
478
-
479
- #### 5. Canary Tokens / Honey Tokens (sandbox)
480
-
481
- Injects fake credentials into the sandbox environment before installing a package. If the package attempts to exfiltrate these honey tokens via HTTP, DNS, filesystem, or stdout, it's flagged as confirmed malicious.
482
-
483
- 6 honeypot credentials are injected:
484
- - `GITHUB_TOKEN` / `NPM_TOKEN` — Package registry tokens
485
- - `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` — Cloud credentials
486
- - `SLACK_WEBHOOK_URL` / `DISCORD_WEBHOOK_URL` — Messaging webhooks
487
-
488
- Both dynamic tokens (random per session, from `canary-tokens.js`) and static fallback tokens (in `sandbox-runner.sh`) are used for defense in depth.
489
-
490
- ```bash
491
- muaddib sandbox suspicious-package
492
- ```
493
-
494
- ### Full temporal scan
495
-
496
- Enable all temporal analysis features at once:
497
-
498
- ```bash
499
- muaddib scan . --temporal-full
500
- ```
501
-
502
- ### Usage examples
503
-
504
- ```bash
505
- # Full behavioral scan (all 5 features)
506
- muaddib scan . --temporal-full
507
-
508
- # Only lifecycle script detection
509
- muaddib scan . --temporal
510
-
511
- # AST diff + maintainer change
512
- muaddib scan . --temporal-ast --temporal-maintainer
513
-
514
- # Sandbox with canary tokens (enabled by default)
515
- muaddib sandbox suspicious-package
516
-
517
- # Sandbox without canary tokens
518
- muaddib sandbox suspicious-package --no-canary
519
- ```
520
-
521
- ### New detection rules (v2.0)
522
-
523
- | Rule ID | Name | Severity | Feature |
524
- |---------|------|----------|---------|
525
- | MUADDIB-TEMPORAL-001 | Sudden Lifecycle Script Added (Critical) | CRITICAL | `--temporal` |
526
- | MUADDIB-TEMPORAL-002 | Sudden Lifecycle Script Added | HIGH | `--temporal` |
527
- | MUADDIB-TEMPORAL-003 | Lifecycle Script Modified | MEDIUM | `--temporal` |
528
- | MUADDIB-TEMPORAL-AST-001 | Dangerous API Added (Critical) | CRITICAL | `--temporal-ast` |
529
- | MUADDIB-TEMPORAL-AST-002 | Dangerous API Added (High) | HIGH | `--temporal-ast` |
530
- | MUADDIB-TEMPORAL-AST-003 | Dangerous API Added (Medium) | MEDIUM | `--temporal-ast` |
531
- | MUADDIB-PUBLISH-001 | Publish Burst Detected | HIGH | `--temporal-publish` |
532
- | MUADDIB-PUBLISH-002 | Dormant Package Spike | HIGH | `--temporal-publish` |
533
- | MUADDIB-PUBLISH-003 | Rapid Version Succession | MEDIUM | `--temporal-publish` |
534
- | MUADDIB-MAINTAINER-001 | New Maintainer Added | HIGH | `--temporal-maintainer` |
535
- | MUADDIB-MAINTAINER-002 | Suspicious Maintainer Detected | CRITICAL | `--temporal-maintainer` |
536
- | MUADDIB-MAINTAINER-003 | Sole Maintainer Changed | HIGH | `--temporal-maintainer` |
537
- | MUADDIB-MAINTAINER-004 | New Publisher Detected | MEDIUM | `--temporal-maintainer` |
538
- | MUADDIB-CANARY-001 | Canary Token Exfiltration | CRITICAL | sandbox |
539
-
540
- ### Why it matters
541
-
542
- These features detect attacks like:
543
- - **Shai-Hulud** (2025): Would be caught by temporal lifecycle + AST diff (sudden `postinstall` + `child_process` added)
544
- - **ua-parser-js** (2021): Would be caught by maintainer change + lifecycle script detection
545
- - **event-stream** (2018): Would be caught by sole maintainer change + AST diff (new `flatmap-stream` dependency with `eval`)
546
- - **coa/rc** (2021): Would be caught by publish burst + lifecycle script detection
547
-
548
- All without needing a single IOC entry.
549
-
550
- ---
551
-
552
- ## IOC Sources
553
-
554
- MUAD'DIB aggregates threat intelligence from verified sources only:
555
-
556
- | Source | Type | Coverage |
557
- |--------|------|----------|
558
- | [OSV.dev npm dump](https://osv.dev) | Bulk zip | 200,000+ npm MAL-* entries |
559
- | [OSV.dev PyPI dump](https://osv.dev) | Bulk zip | 14,000+ PyPI MAL-* entries |
560
- | [GenSecAI Shai-Hulud Detector](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector) | GitHub | 700+ Shai-Hulud packages |
561
- | [DataDog Security Labs](https://github.com/DataDog/indicators-of-compromise) | GitHub | Consolidated IOCs from 7 vendors |
562
- | [OSSF Malicious Packages](https://github.com/ossf/malicious-packages) | OSV API | 8000+ malware reports |
563
- | [GitHub Advisory](https://github.com/advisories?query=type%3Amalware) | OSV API | Malware-tagged advisories |
564
- | Snyk Known Malware | Static | Historical attacks |
565
- | Socket.dev / Phylum | Static | Manual additions |
179
+ ### 14 parallel scanners
180
+
181
+ | Scanner | Detection |
182
+ |---------|-----------|
183
+ | AST Parse (acorn) | eval, Function, credential theft, binary droppers, prototype hooks |
184
+ | Pattern Matching | Shell commands, reverse shells, dead man's switch |
185
+ | Dataflow Analysis | Credential read + network send (intra-file and cross-file) |
186
+ | Obfuscation Detection | JS obfuscation patterns (skip .min.js) |
187
+ | Deobfuscation Pre-processing | String concat, charcode, base64, hex array, const propagation |
188
+ | Inter-module Dataflow | Cross-file taint propagation (3-hop chains, class methods) |
189
+ | Intent Coherence | Intra-file source-sink pairing (credential + eval/network) |
190
+ | Typosquatting | npm + PyPI (Levenshtein distance) |
191
+ | Python Scanner | requirements.txt, setup.py, pyproject.toml, 14K+ PyPI IOCs |
192
+ | Shannon Entropy | High-entropy strings (5.5 bits + 50 chars min) |
193
+ | AI Config Scanner | .cursorrules, CLAUDE.md, copilot-instructions.md injection |
194
+ | Package/Dependencies | Lifecycle scripts, IOC matching (225K+ packages) |
195
+ | GitHub Actions | Shai-Hulud backdoor detection |
196
+ | Hash Scanner | Known malicious file hashes |
197
+
198
+ ### 129 detection rules
199
+
200
+ All rules are mapped to MITRE ATT&CK techniques. See [SECURITY.md](SECURITY.md#detection-rules-v262) for the complete rules reference.
201
+
202
+ ### Detected campaigns
203
+
204
+ | Campaign | Status |
205
+ |----------|--------|
206
+ | Shai-Hulud v1/v2/v3 (2025) | Detected |
207
+ | event-stream (2018) | Detected |
208
+ | eslint-scope (2018) | Detected |
209
+ | Protestware (node-ipc, colors, faker) | Detected |
210
+ | Typosquats (crossenv, mongose, babelcli) | Detected |
566
211
 
567
212
  ---
568
213
 
@@ -570,24 +215,15 @@ MUAD'DIB aggregates threat intelligence from verified sources only:
570
215
 
571
216
  The VS Code extension automatically scans your npm projects.
572
217
 
573
- ### Installation
574
-
575
- Search "MUAD'DIB" in VS Code Extensions, or:
576
-
577
218
  ```bash
578
219
  code --install-extension dnszlsk.muaddib-vscode
579
220
  ```
580
221
 
581
- ### Commands
582
-
583
222
  - `MUAD'DIB: Scan Project` - Scan entire project
584
223
  - `MUAD'DIB: Scan Current File` - Scan current file
224
+ - Settings: `muaddib.autoScan`, `muaddib.webhookUrl`, `muaddib.failLevel`
585
225
 
586
- ### Settings
587
-
588
- - `muaddib.autoScan` - Auto-scan on project open (default: true)
589
- - `muaddib.webhookUrl` - Discord/Slack webhook URL
590
- - `muaddib.failLevel` - Alert level (critical/high/medium/low)
226
+ See [vscode-extension/README.md](vscode-extension/README.md) for full documentation.
591
227
 
592
228
  ---
593
229
 
@@ -595,8 +231,6 @@ code --install-extension dnszlsk.muaddib-vscode
595
231
 
596
232
  ### GitHub Actions (Marketplace)
597
233
 
598
- Use the official MUAD'DIB action from the GitHub Marketplace:
599
-
600
234
  ```yaml
601
235
  name: Security Scan
602
236
 
@@ -617,130 +251,28 @@ jobs:
617
251
  sarif: 'results.sarif'
618
252
  ```
619
253
 
620
- #### Action Inputs
621
-
622
254
  | Input | Description | Default |
623
255
  |-------|-------------|---------|
624
256
  | `path` | Path to scan | `.` |
625
- | `fail-on` | Minimum severity to fail (critical/high/medium/low) | `high` |
626
- | `sarif` | Path for SARIF output file | `` |
627
- | `paranoid` | Enable ultra-strict detection | `false` |
628
-
629
- #### Action Outputs
630
-
631
- | Output | Description |
632
- |--------|-------------|
633
- | `sarif-file` | Path to generated SARIF file |
634
- | `risk-score` | Risk score (0-100) |
635
- | `threats-count` | Number of threats detected |
636
- | `exit-code` | Exit code (0 = clean) |
257
+ | `fail-on` | Minimum severity to fail | `high` |
258
+ | `sarif` | SARIF output file path | |
259
+ | `paranoid` | Ultra-strict detection | `false` |
637
260
 
638
- Alerts appear in Security > Code scanning alerts.
639
-
640
- ---
641
-
642
- ## Architecture
261
+ ### Pre-commit hooks
643
262
 
263
+ ```bash
264
+ muaddib init-hooks # Auto-detect (husky/pre-commit/git)
265
+ muaddib init-hooks --type husky # Force husky
266
+ muaddib init-hooks --mode diff # Only block NEW threats
644
267
  ```
645
- MUAD'DIB 2.6.1 Scanner
646
- |
647
- +-- IOC Match (225,000+ packages, JSON DB)
648
- | +-- OSV.dev npm dump (200K+ MAL-* entries)
649
- | +-- OSV.dev PyPI dump (14K+ MAL-* entries)
650
- | +-- GenSecAI Shai-Hulud Detector
651
- | +-- DataDog Consolidated IOCs
652
- | +-- OSSF Malicious Packages (via OSV)
653
- | +-- GitHub Advisory (malware)
654
- | +-- Snyk Known Malware
655
- | +-- Static IOCs (Socket, Phylum)
656
- |
657
- +-- Deobfuscation Pre-processing (v2.2.5, --no-deobfuscate to disable)
658
- | +-- String concat folding, CharCode reconstruction
659
- | +-- Base64 decode, Hex array resolution
660
- | +-- Const propagation (Phase 2)
661
- |
662
- +-- Inter-module Dataflow (v2.2.6, --no-module-graph to disable)
663
- | +-- Module dependency graph, tainted export annotation
664
- | +-- 3-hop re-export chains, class method analysis
665
- | +-- Cross-file credential read -> network sink detection
666
- |
667
- +-- Intent Coherence Analysis (v2.6.0)
668
- | +-- Intra-file source-sink pairing (credential read + eval/network in same file)
669
- | +-- Cross-file detection delegated to module-graph (proven taint paths only)
670
- | +-- LOW severity threats excluded (respects FP reductions)
671
- |
672
- +-- 14 Parallel Scanners (129 rules)
673
- | +-- AST Parse (acorn) — eval/Function, credential CLI theft, binary droppers, prototype hooks
674
- | +-- Pattern Matching (shell, scripts)
675
- | +-- Obfuscation Detection (skip .min.js, ignore hex/unicode alone)
676
- | +-- Typosquat Detection (npm + PyPI, Levenshtein)
677
- | +-- Python Scanner (requirements.txt, setup.py, pyproject.toml)
678
- | +-- Shannon Entropy (string-level, 5.5 bits + 50 chars min)
679
- | +-- JS Obfuscation Patterns (_0x* vars, encoded arrays, eval+entropy)
680
- | +-- GitHub Actions Scanner
681
- | +-- AI Config Scanner (.cursorrules, CLAUDE.md, copilot-instructions.md)
682
- | +-- Package, Dependencies, Hash, npm-registry, Dataflow scanners
683
- |
684
- +-- Supply Chain Anomaly Detection (v2.0)
685
- | +-- Temporal Lifecycle Script Detection (--temporal)
686
- | +-- Temporal AST Diff (--temporal-ast)
687
- | +-- Publish Frequency Anomaly (--temporal-publish)
688
- | +-- Maintainer Change Detection (--temporal-maintainer)
689
- | +-- Canary Tokens / Honey Tokens (sandbox)
690
- |
691
- +-- Validation & Observability (v2.1)
692
- | +-- Datadog 17K Benchmark (88.2% raw, ~100% JS/Node.js adjusted)
693
- | +-- Ground Truth Dataset (51 real-world attacks, 93.9% TPR)
694
- | +-- Detection Time Logging (first_seen tracking, lead time metrics)
695
- | +-- FP Rate Tracking (daily stats, false positive rate)
696
- | +-- Score Breakdown (explainable per-rule scoring)
697
- | +-- Threat Feed API (HTTP server, JSON feed for SIEM)
698
- |
699
- +-- FP Reduction Post-processing (v2.2.8-v2.3.1, v2.5.7-v2.5.8, v2.5.15-v2.5.16)
700
- | +-- Count-based severity downgrade (dynamic_require, dataflow, module_compile, etc.)
701
- | +-- Framework prototype scoring cap + HTTP client whitelist
702
- | +-- Obfuscation in dist/build/.cjs/.mjs/.js >100KB → LOW
703
- | +-- Safe env var + prefix filtering + DATAFLOW_SAFE_ENV_VARS
704
- | +-- Dataflow telemetry source categorization (os.platform/arch → telemetry_read)
705
- | +-- DEP whitelist (es5-ext, bootstrap-sass) + npm alias skip
706
- | +-- IOC wildcard audit (v2.5.8): FPR 10.8% → 6.0%
707
- | +-- P5 heuristic precision (v2.5.15): 7 fixes
708
- | +-- P6 compound detection precision (v2.5.16): 6 fixes
709
- |
710
- +-- Per-File Max Scoring (v2.2.11)
711
- | +-- Score = max(file_scores) + package_level_score
712
- | +-- Eliminates score accumulation across many files
713
- | +-- Package-level threats (lifecycle, typosquat, IOC) scored separately
714
- |
715
- +-- Sandbox Monkey-Patching Preload (v2.4.9)
716
- | +-- Runtime time manipulation (Date.now, setTimeout→0, setInterval→immediate)
717
- | +-- Network/filesystem/process/env interception and logging
718
- | +-- Multi-run [0h, 72h, 7d] for time-bomb detection (T1497.003)
719
- |
720
- +-- Security Audit (v2.5.0-v2.5.6)
721
- | +-- 41 issues remediated (14 CRITICAL, 18 HIGH, 9 MEDIUM)
722
- | +-- Native addon path traversal, atomic writes, AST bypasses
723
- |
724
- +-- Audit Hardening (v2.5.13-v2.5.14)
725
- | +-- Scoring: plugin loader threshold, lifecycle CRITICAL floor, percentage guard 40%
726
- | +-- AST: eval alias, globalThis indirect, require(obj.prop), variable reassignment
727
- | +-- Dataflow: Promise .then() tainting, JSON taint propagation
728
- | +-- Shell: mkfifo+nc, base64|bash, wget+base64 (3 new patterns)
729
- | +-- Entropy: fragment cluster, windowed analysis
730
- | +-- 8 new rules (SHELL-013 to 015, ENTROPY-004, +4 audit fixes)
731
- |
732
- +-- Paranoid Mode (ultra-strict)
733
- +-- Docker Sandbox (behavioral analysis, network capture, canary tokens, CI-aware, preload)
734
- +-- Zero-Day Monitor (internal: npm + PyPI RSS polling, Discord alerts, daily report)
735
- |
736
- v
737
- Dataflow Analysis (credential read -> network send)
738
- |
739
- v
740
- Threat Enrichment (rules, MITRE ATT&CK, playbooks)
741
- |
742
- v
743
- Output (CLI, JSON, HTML, SARIF, Webhook, Threat Feed)
268
+
269
+ With pre-commit framework:
270
+ ```yaml
271
+ repos:
272
+ - repo: https://github.com/DNSZLSK/muad-dib
273
+ rev: v2.6.2
274
+ hooks:
275
+ - id: muaddib-scan
744
276
  ```
745
277
 
746
278
  ---
@@ -749,53 +281,14 @@ Output (CLI, JSON, HTML, SARIF, Webhook, Threat Feed)
749
281
 
750
282
  | Metric | Result | Details |
751
283
  |--------|--------|---------|
752
- | **Wild TPR** (Datadog 17K) | **88.2%** raw · **~100%** adjusted | 17,922 real malware samples. 2,077 misses are all out-of-scope (see below) |
753
- | **TPR** (Ground Truth) | **93.9%** (46/49) | 51 real-world attacks (49 active). 3 out-of-scope: browser-only (3) |
754
- | **FPR** (Benign, global) | **12.3%** (65/532) | 532 npm packages, real source code via `npm pack`, threshold > 20 |
755
- | **ADR** (Adversarial + Holdout) | **97.3%** (73/75) | 53 adversarial + 40 holdout evasive samples (75 available on disk). 2 misses: `require-cache-poison` (P3 trade-off), `getter-defineProperty-exfil` |
756
-
757
- **Datadog 17K benchmark** — [DataDog Malicious Software Packages Dataset](https://github.com/DataDog/malicious-software-packages-dataset), 17,922 real malware samples (npm). Raw TPR: 88.2% (15,810/17,922). The 2,077 misses (score=0) were manually categorized:
758
-
759
- | Category | Count | Reason |
760
- |----------|-------|--------|
761
- | Phishing pages (HTML/CSS/JS frontend) | 1,233 | No Node.js APIs (no `require`, `child_process`, `fs`, `process.env`). Fake login pages, redirects, captchas. |
762
- | Native binaries (no JS files) | 824 | Platform-specific binaries (darwin-arm64, linux-x64, etc.). 201 from @42ailab alone. |
763
- | Corrected libraries | 20 | Temporarily compromised then fixed. Malicious code removed before scan. |
764
-
765
- All 2,077 misses lack Node.js malware patterns. MUAD'DIB performs AST-based Node.js static analysis — phishing HTML and native binaries are out of scope. Adjusted TPR on JS/Node.js malware: **~100%** (15,810/~15,845). See [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md#14-datadog-17k-benchmark).
766
-
767
- **FPR by package size** — FPR correlates linearly with package size. Per-file max scoring (v2.2.11) significantly reduces FP on medium/large packages:
768
-
769
- | Category | Packages | FP | FPR |
770
- |----------|----------|-----|-----|
771
- | Small (<10 JS files) | 290 | 18 | **6.2%** |
772
- | Medium (10-50 JS files) | 135 | 16 | 11.9% |
773
- | Large (50-100 JS files) | 40 | 10 | 25.0% |
774
- | Very large (100+ JS files) | 62 | 25 | 40.3% |
775
-
776
- **FPR progression**: 0% (invalid, empty dirs, v2.2.0-v2.2.6) → 38% (first real measurement, v2.2.7) → 19.4% (v2.2.8) → 17.5% (v2.2.9) → ~13% (v2.2.11, per-file max scoring) → 8.9% (v2.3.0, P2) → 7.4% (v2.3.1, P3) → 6.0% (v2.5.8, P4 + IOC wildcard audit) → ~13.6% (v2.5.14, audit hardening added stricter detection) → **12.3%** (v2.5.16, P5 + P6) → **12.3%** (v2.6.0, intent graph v2 — zero FP added) → **12.3%** (v2.6.1, module-graph bounded path — zero FP added)
777
-
778
- > **Note on FPR evolution:** The historic 6.0% FPR (v2.5.8) relied on a `BENIGN_PACKAGE_WHITELIST` that excluded certain known packages from scoring — a data leakage bias removed in v2.5.10. The current 12.3% FPR is an honest measurement without whitelisting, against 532 real benign packages. The intent graph (v2.6.0) adds zero false positives by using intra-file pairing only and excluding LOW-severity threats.
779
-
780
- **Holdout progression** (pre-tuning scores, rules frozen):
781
-
782
- | Holdout | Score | Focus |
783
- |---------|-------|-------|
784
- | v1 | 30% (3/10) | General patterns |
785
- | v2 | 40% (4/10) | Env charcode, lifecycle, prototype |
786
- | v3 | 60% (6/10) | Require cache, DNS TXT, reverse shell |
787
- | v4 | **80%** (8/10) | Deobfuscation effectiveness |
788
- | v5 | 50% (5/10) | Inter-module dataflow (new scanner) |
789
-
790
- - **Wild TPR** (Datadog Benchmark): detection rate on 17,922 real malware packages from the [DataDog Malicious Software Packages Dataset](https://github.com/DataDog/malicious-software-packages-dataset). Raw 88.2% (15,810/17,922). Adjusted ~100% on JS/Node.js malware when excluding out-of-scope samples (1,233 phishing HTML pages, 824 native binaries, 20 corrected libraries). See [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md#14-datadog-17k-benchmark).
791
- - **TPR** (True Positive Rate): detection rate on 49 real-world supply-chain attacks (event-stream, ua-parser-js, coa, flatmap-stream, eslint-scope, solana-web3js, and 43 more). 3 misses are browser-only (lottie-player, polyfill-io, trojanized-jquery) — see [Threat Model](docs/threat-model.md).
792
- - **FPR** (False Positive Rate): packages scoring > 20 out of 529 real npm packages (source code scanned, not empty dirs).
793
- - **ADR** (Adversarial Detection Rate): detection rate on 120 evasive malicious samples — 53 adversarial + 40 holdout (6 adversarial waves + 4 holdout batches). 75 available on disk. 2 misses on available samples: `require-cache-poison` (P3 trade-off), `getter-defineProperty-exfil`.
794
- - **Holdout** (pre-tuning): detection rate on 10 unseen samples with rules frozen (measures generalization)
284
+ | **Wild TPR** (Datadog 17K) | **88.2%** raw / **~100%** adjusted | 17,922 real malware. 2,077 out-of-scope (phishing, binaries, corrected) |
285
+ | **TPR** (Ground Truth) | **93.9%** (46/49) | 51 real attacks. 3 out-of-scope: browser-only |
286
+ | **FPR** (Benign) | **12.1%** (64/529) | 529 npm packages, real source via `npm pack` |
287
+ | **ADR** (Adversarial + Holdout) | **94.8%** (73/77) | 53 adversarial + 40 holdout (77 available on disk) |
795
288
 
796
- Datasets: 17,922 Datadog malware samples, 532 npm + 132 PyPI benign packages, 120 adversarial/holdout samples (75 available on disk), 51 ground-truth attacks (65 documented malware packages). **1932 tests**, 86% code coverage.
289
+ **1940 tests** across 44 files, 86% code coverage. **129 rules** (124 RULES + 5 PARANOID).
797
290
 
798
- See [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md) for the full experimental protocol.
291
+ See [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md) for the full experimental protocol, holdout history, and Datadog benchmark details.
799
292
 
800
293
  ---
801
294
 
@@ -829,13 +322,11 @@ npm test
829
322
 
830
323
  ### Testing
831
324
 
832
- - **1932 unit/integration tests** across 44 modular test files - 86% code coverage via [Codecov](https://codecov.io/gh/DNSZLSK/muad-dib)
833
- - **56 fuzz tests** - Malformed YAML, invalid JSON, binary files, ReDoS, unicode, 10MB inputs
834
- - **Datadog 17K benchmark** - 17,922 real malware samples, 88.2% raw TPR, ~100% on JS/Node.js malware (2,077 out-of-scope misses: phishing, binaries, corrected libs)
835
- - **120 adversarial/holdout samples** - 53 adversarial + 40 holdout (75 available on disk), 73/75 detection rate (97.3% ADR). 2 misses: `require-cache-poison` (P3 trade-off), `getter-defineProperty-exfil`
836
- - **Ground truth validation** - 51 real-world attacks (46/49 detected = 93.9% TPR). 3 out-of-scope: browser-only (lottie-player, polyfill-io, trojanized-jquery)
837
- - **False positive validation** - 12.3% FPR global (65/532) on real npm source code via `npm pack`
838
- - **ESLint security audit** - `eslint-plugin-security` with 14 rules enabled
325
+ - **1940 tests** across 44 modular test files - 86% code coverage
326
+ - **56 fuzz tests** - Malformed inputs, ReDoS, unicode, binary
327
+ - **Datadog 17K benchmark** - 17,922 real malware samples
328
+ - **Ground truth validation** - 51 real-world attacks (93.9% TPR)
329
+ - **False positive validation** - 12.1% FPR on 529 real npm packages
839
330
 
840
331
  ---
841
332
 
@@ -847,10 +338,13 @@ npm test
847
338
 
848
339
  ## Documentation
849
340
 
850
- - [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md) - Experimental protocol, raw holdout scores, attack sources
341
+ - [Documentation Index](docs/INDEX.md) - All documentation in one place
342
+ - [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md) - Experimental protocol, holdout scores
851
343
  - [Threat Model](docs/threat-model.md) - What MUAD'DIB detects and doesn't detect
852
- - [Security Audit Report v1.4.1](docs/MUADDIB_Security_Audit_Report_v1.4.1.pdf) - Full security audit (58 issues fixed)
853
- - [IOCs YAML](iocs/) - Threat database
344
+ - [Adversarial Evaluation](ADVERSARIAL.md) - Red team samples and ADR results
345
+ - [Security Policy](SECURITY.md) - Detection rules reference (129 rules)
346
+ - [Security Audit](docs/SECURITY_AUDIT.md) - Bypass validation report
347
+ - [FP Analysis](docs/EVALUATION.md) - Historical false positive analysis
854
348
 
855
349
  ---
856
350
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muaddib-scanner",
3
- "version": "2.6.2",
3
+ "version": "2.6.4",
4
4
  "description": "Supply-chain threat detection & response for npm & PyPI/Python",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -48,7 +48,8 @@
48
48
  "acorn": "8.16.0",
49
49
  "acorn-walk": "8.3.5",
50
50
  "adm-zip": "0.5.16",
51
- "js-yaml": "4.1.1"
51
+ "js-yaml": "4.1.1",
52
+ "muaddib-scanner": "^2.6.3"
52
53
  },
53
54
  "overrides": {
54
55
  "loadash": "0.0.0-security"
@@ -545,25 +545,31 @@ async function scrapeDatadogIOCs() {
545
545
 
546
546
  for (const parts of rows) {
547
547
  const name = parts[0] || '';
548
- const versions = parts[1] || '*';
548
+ const versionsStr = parts[1] || '*';
549
549
  const vendors = parts[2] || 'datadog';
550
550
 
551
551
  if (name && name !== 'package_name' && name !== 'name') {
552
- packages.push({
553
- id: `DATADOG-${name}`,
554
- name: name,
555
- version: versions || '*',
556
- severity: 'critical',
557
- confidence: 'high',
558
- source: 'datadog-consolidated',
559
- description: `Compromised package (sources: ${vendors})`,
560
- references: ['https://securitylabs.datadoghq.com/articles/shai-hulud-2.0-npm-worm/'],
561
- mitre: 'T1195.002',
562
- freshness: createFreshness('datadog', 'high')
563
- });
552
+ // Split comma-separated multi-version strings (e.g. "4.18.1, 5.11.3")
553
+ const versionList = versionsStr.includes(',')
554
+ ? versionsStr.split(',').map(v => v.trim()).filter(Boolean)
555
+ : [versionsStr];
556
+ for (const ver of versionList) {
557
+ packages.push({
558
+ id: `DATADOG-${name}`,
559
+ name: name,
560
+ version: ver || '*',
561
+ severity: 'critical',
562
+ confidence: 'high',
563
+ source: 'datadog-consolidated',
564
+ description: `Compromised package (sources: ${vendors})`,
565
+ references: ['https://securitylabs.datadoghq.com/articles/shai-hulud-2.0-npm-worm/'],
566
+ mitre: 'T1195.002',
567
+ freshness: createFreshness('datadog', 'high')
568
+ });
569
+ }
564
570
  }
565
571
  }
566
- console.log(`[SCRAPER] ${packages.length} packages (consolidated)`);
572
+ console.log(`[SCRAPER] ${packages.length} IOC entries (consolidated)`);
567
573
  }
568
574
 
569
575
  // DataDog specific file
@@ -858,18 +864,21 @@ async function scrapeGitHubAdvisory() {
858
864
  if (isMalware) {
859
865
  for (const affected of vuln.affected || []) {
860
866
  if (affected.package && affected.package.ecosystem === 'npm') {
861
- packages.push({
862
- id: vuln.id,
863
- name: affected.package.name,
864
- version: '*',
865
- severity: 'critical',
866
- confidence: 'high',
867
- source: 'github-advisory',
868
- description: (vuln.summary || 'Malicious package').slice(0, 200),
869
- references: ['https://github.com/advisories/' + vuln.id],
870
- mitre: 'T1195.002',
871
- freshness: createFreshness('github-advisory', 'high')
872
- });
867
+ const versions = extractVersions(affected);
868
+ for (const ver of versions) {
869
+ packages.push({
870
+ id: vuln.id,
871
+ name: affected.package.name,
872
+ version: ver,
873
+ severity: 'critical',
874
+ confidence: 'high',
875
+ source: 'github-advisory',
876
+ description: (vuln.summary || 'Malicious package').slice(0, 200),
877
+ references: ['https://github.com/advisories/' + vuln.id],
878
+ mitre: 'T1195.002',
879
+ freshness: createFreshness('github-advisory', 'high')
880
+ });
881
+ }
873
882
  }
874
883
  }
875
884
  }
@@ -339,6 +339,15 @@ function createOptimizedIOCs(iocs) {
339
339
  * @param {Object} fullIOCs - Full IOCs object with packages array
340
340
  * @returns {Object} Compact IOCs
341
341
  */
342
+ // Legitimate packages with version-specific compromises only.
343
+ // These must never become wildcards (all-version flags) because only
344
+ // specific versions were malicious — flagging all versions is a false positive.
345
+ const NEVER_WILDCARD = new Set([
346
+ 'event-stream', 'ua-parser-js', 'coa', 'rc',
347
+ 'colors', 'faker', 'node-ipc',
348
+ 'posthog-node', 'ngx-bootstrap', '@asyncapi/specs'
349
+ ]);
350
+
342
351
  function generateCompactIOCs(fullIOCs) {
343
352
  const wildcards = [];
344
353
  const versioned = Object.create(null);
@@ -353,6 +362,10 @@ function generateCompactIOCs(fullIOCs) {
353
362
  }
354
363
 
355
364
  if (p.version === '*') {
365
+ if (NEVER_WILDCARD.has(p.name)) {
366
+ // Legitimate package — skip wildcard, treat as version-unknown
367
+ continue;
368
+ }
356
369
  wildcards.push(p.name);
357
370
  } else {
358
371
  if (!versioned[p.name]) versioned[p.name] = [];
@@ -497,4 +510,4 @@ function verifyIOCHMAC(data, hmac) {
497
510
  }
498
511
  }
499
512
 
500
- module.exports = { updateIOCs, loadCachedIOCs, invalidateCache, generateCompactIOCs, expandCompactIOCs, mergeIOCs, createOptimizedIOCs, generateIOCHMAC, verifyIOCHMAC };
513
+ module.exports = { updateIOCs, loadCachedIOCs, invalidateCache, generateCompactIOCs, expandCompactIOCs, mergeIOCs, createOptimizedIOCs, generateIOCHMAC, verifyIOCHMAC, NEVER_WILDCARD };