muaddib-scanner 2.2.19 → 2.2.22
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/.gitattributes +18 -0
- package/README.fr.md +819 -825
- package/README.md +822 -822
- package/bin/muaddib.js +868 -849
- package/docker/Dockerfile +19 -18
- package/docker/sandbox-runner.sh +313 -292
- package/package.json +61 -61
- package/src/commands/evaluate.js +484 -484
- package/src/diff.js +411 -411
- package/src/hooks-init.js +264 -258
- package/src/index.js +439 -437
- package/src/ioc/scraper.js +1293 -1293
- package/src/monitor.js +1817 -1764
- package/src/sandbox.js +631 -620
- package/src/scanner/ast-detectors.js +946 -933
- package/src/scanner/ast.js +96 -96
- package/src/scanner/github-actions.js +96 -96
- package/src/scanner/module-graph.js +2 -2
- package/src/scanner/obfuscation.js +128 -128
- package/src/scanner/shell.js +48 -48
- package/src/shared/download.js +181 -171
- package/src/webhook.js +413 -353
package/README.md
CHANGED
|
@@ -1,822 +1,822 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="assets/muaddibLogo.png" alt="MUAD'DIB Logo" width="700">
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
|
-
<p align="center">
|
|
6
|
-
<a href="https://www.npmjs.com/package/muaddib-scanner"><img src="https://img.shields.io/npm/v/muaddib-scanner" alt="npm version"></a>
|
|
7
|
-
<a href="https://github.com/DNSZLSK/muad-dib/actions/workflows/scan.yml"><img src="https://github.com/DNSZLSK/muad-dib/actions/workflows/scan.yml/badge.svg" alt="CI"></a>
|
|
8
|
-
<a href="https://codecov.io/gh/DNSZLSK/muad-dib"><img src="https://codecov.io/gh/DNSZLSK/muad-dib/branch/master/graph/badge.svg" alt="Coverage"></a>
|
|
9
|
-
<a href="https://scorecard.dev/viewer/?uri=github.com/DNSZLSK/muad-dib"><img src="https://api.scorecard.dev/projects/github.com/DNSZLSK/muad-dib/badge" alt="OpenSSF Scorecard"></a>
|
|
10
|
-
<img src="https://img.shields.io/badge/license-MIT-green" alt="License">
|
|
11
|
-
<img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen" alt="Node">
|
|
12
|
-
<img src="https://img.shields.io/badge/IOCs-225%2C000%2B-red" alt="IOCs">
|
|
13
|
-
</p>
|
|
14
|
-
|
|
15
|
-
<p align="center">
|
|
16
|
-
<a href="#installation">Installation</a> |
|
|
17
|
-
<a href="#usage">Usage</a> |
|
|
18
|
-
<a href="#features">Features</a> |
|
|
19
|
-
<a href="#vs-code">VS Code</a> |
|
|
20
|
-
<a href="#ci-cd">CI/CD</a>
|
|
21
|
-
</p>
|
|
22
|
-
|
|
23
|
-
<p align="center">
|
|
24
|
-
<a href="README.fr.md">Version francaise</a>
|
|
25
|
-
</p>
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## Why MUAD'DIB?
|
|
30
|
-
|
|
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
|
-
|
|
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) + **behavioral anomaly detection** (v2.0) + **ground truth validation** (v2.1) to detect threats AND guide your response — even before they appear in any IOC database.
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## Positioning
|
|
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.
|
|
40
|
-
|
|
41
|
-
**For enterprise protection**, use:
|
|
42
|
-
- [Socket.dev](https://socket.dev) - ML behavioral analysis, cloud sandboxing
|
|
43
|
-
- [Snyk](https://snyk.io) - Massive vulnerability database, CI/CD integrations
|
|
44
|
-
- [Opengrep](https://opengrep.dev) - Advanced dataflow analysis, Semgrep rules
|
|
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
|
-
---
|
|
49
|
-
|
|
50
|
-
## Installation
|
|
51
|
-
|
|
52
|
-
### npm (recommended)
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
npm install -g muaddib-scanner
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### From source
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
git clone https://github.com/DNSZLSK/muad-dib
|
|
62
|
-
cd muad-dib
|
|
63
|
-
npm install
|
|
64
|
-
npm link
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
## Usage
|
|
70
|
-
|
|
71
|
-
### Basic scan
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
muaddib scan .
|
|
75
|
-
muaddib scan /path/to/project
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Scans both npm (package.json, node_modules) and Python (requirements.txt, setup.py, pyproject.toml) dependencies.
|
|
79
|
-
|
|
80
|
-
### Interactive mode
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
muaddib
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Launches an interactive menu to guide you through all features.
|
|
87
|
-
|
|
88
|
-
### Safe install
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
muaddib install <package>
|
|
92
|
-
muaddib install lodash axios --save-dev
|
|
93
|
-
muaddib i express -g
|
|
94
|
-
muaddib install suspicious-pkg --force # Force install despite threats
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Scans packages for threats BEFORE installing. Blocks known malicious packages.
|
|
98
|
-
|
|
99
|
-
### Risk score
|
|
100
|
-
|
|
101
|
-
Each scan displays a 0-100 risk score:
|
|
102
|
-
|
|
103
|
-
```
|
|
104
|
-
[SCORE] 58/100 [***********---------] HIGH
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Explain mode (full details)
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
muaddib scan . --explain
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
Shows for each detection:
|
|
114
|
-
- Rule ID
|
|
115
|
-
- MITRE ATT&CK technique
|
|
116
|
-
- References (articles, CVEs)
|
|
117
|
-
- Response playbook
|
|
118
|
-
|
|
119
|
-
### Export
|
|
120
|
-
|
|
121
|
-
```bash
|
|
122
|
-
muaddib scan . --json > results.json # JSON
|
|
123
|
-
muaddib scan . --html report.html # HTML
|
|
124
|
-
muaddib scan . --sarif results.sarif # SARIF (GitHub Security)
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### Severity threshold
|
|
128
|
-
|
|
129
|
-
```bash
|
|
130
|
-
muaddib scan . --fail-on critical # Fail only on CRITICAL
|
|
131
|
-
muaddib scan . --fail-on high # Fail on HIGH and CRITICAL (default)
|
|
132
|
-
muaddib scan . --fail-on medium # Fail on MEDIUM, HIGH, CRITICAL
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### Paranoid mode
|
|
136
|
-
|
|
137
|
-
```bash
|
|
138
|
-
muaddib scan . --paranoid
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
Ultra-strict detection with lower tolerance. Useful for critical projects. Detects any network access, subprocess execution, dynamic code evaluation, and sensitive file access.
|
|
142
|
-
|
|
143
|
-
### Discord/Slack webhook
|
|
144
|
-
|
|
145
|
-
```bash
|
|
146
|
-
muaddib scan . --webhook "https://discord.com/api/webhooks/..."
|
|
147
|
-
```
|
|
148
|
-
|
|
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.
|
|
173
|
-
|
|
174
|
-
### Scrape IOCs (full, ~5 minutes)
|
|
175
|
-
|
|
176
|
-
```bash
|
|
177
|
-
muaddib scrape
|
|
178
|
-
```
|
|
179
|
-
|
|
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
|
|
191
|
-
|
|
192
|
-
### Docker Sandbox
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
muaddib sandbox <package-name>
|
|
196
|
-
muaddib sandbox <package-name> --strict
|
|
197
|
-
```
|
|
198
|
-
|
|
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
|
-
- **Scoring engine**: 0-100 risk score based on behavioral severity
|
|
209
|
-
|
|
210
|
-
Use `--strict` to block all non-essential outbound network traffic via iptables.
|
|
211
|
-
|
|
212
|
-
Requires Docker Desktop installed.
|
|
213
|
-
|
|
214
|
-
```bash
|
|
215
|
-
muaddib sandbox lodash # Safe package
|
|
216
|
-
muaddib sandbox suspicious-pkg # Analyze unknown package
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Sandbox network report
|
|
220
|
-
|
|
221
|
-
```bash
|
|
222
|
-
muaddib sandbox-report <package-name>
|
|
223
|
-
muaddib sandbox-report <package-name> --strict
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
Same as `sandbox` but displays a detailed network report: DNS resolutions, HTTP requests, TLS connections, blocked connections (strict mode), and data exfiltration alerts.
|
|
227
|
-
|
|
228
|
-
### Diff (compare versions)
|
|
229
|
-
|
|
230
|
-
```bash
|
|
231
|
-
muaddib diff <ref> [path]
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
Compare threats between the current version and a previous commit/tag. Shows only **NEW** threats introduced since the reference point.
|
|
235
|
-
|
|
236
|
-
```bash
|
|
237
|
-
muaddib diff HEAD~1 # Compare with previous commit
|
|
238
|
-
muaddib diff v1.2.0 # Compare with tag
|
|
239
|
-
muaddib diff main # Compare with branch
|
|
240
|
-
muaddib diff abc1234 # Compare with specific commit
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
Example output:
|
|
244
|
-
```
|
|
245
|
-
[MUADDIB DIFF] Comparing abc1234 -> def5678
|
|
246
|
-
|
|
247
|
-
Risk Score: 25 -> 45 (+20 worse)
|
|
248
|
-
Threats: 3 -> 5
|
|
249
|
-
|
|
250
|
-
NEW threats: 2
|
|
251
|
-
REMOVED threats: 0
|
|
252
|
-
Unchanged: 3
|
|
253
|
-
|
|
254
|
-
NEW THREATS (introduced since v1.2.0)
|
|
255
|
-
------------------------------------
|
|
256
|
-
1. [HIGH] suspicious_dependency
|
|
257
|
-
Known malicious package detected
|
|
258
|
-
File: package.json
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
Use in CI to only fail on **new** threats, not existing technical debt:
|
|
262
|
-
```yaml
|
|
263
|
-
- run: muaddib diff ${{ github.event.pull_request.base.sha }} --fail-on high
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
### Pre-commit hooks
|
|
267
|
-
|
|
268
|
-
```bash
|
|
269
|
-
muaddib init-hooks [options]
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
Automatically scan before each commit. Supports multiple hook systems:
|
|
273
|
-
|
|
274
|
-
```bash
|
|
275
|
-
muaddib init-hooks # Auto-detect (husky/pre-commit/git)
|
|
276
|
-
muaddib init-hooks --type husky # Force husky
|
|
277
|
-
muaddib init-hooks --type pre-commit # Force pre-commit framework
|
|
278
|
-
muaddib init-hooks --type git # Force native git hooks
|
|
279
|
-
muaddib init-hooks --mode diff # Only block NEW threats
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
#### With pre-commit framework
|
|
283
|
-
|
|
284
|
-
Add to `.pre-commit-config.yaml`:
|
|
285
|
-
```yaml
|
|
286
|
-
repos:
|
|
287
|
-
- repo: https://github.com/DNSZLSK/muad-dib
|
|
288
|
-
rev:
|
|
289
|
-
hooks:
|
|
290
|
-
- id: muaddib-scan # Scan all threats
|
|
291
|
-
# - id: muaddib-diff # Or: only new threats
|
|
292
|
-
# - id: muaddib-paranoid # Or: ultra-strict mode
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
#### With husky
|
|
296
|
-
|
|
297
|
-
```bash
|
|
298
|
-
npx husky add .husky/pre-commit "npx muaddib scan . --fail-on high"
|
|
299
|
-
# Or for diff mode:
|
|
300
|
-
npx husky add .husky/pre-commit "npx muaddib diff HEAD --fail-on high"
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
#### Remove hooks
|
|
304
|
-
|
|
305
|
-
```bash
|
|
306
|
-
muaddib remove-hooks [path]
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
Removes all MUAD'DIB hooks (husky and git native).
|
|
310
|
-
|
|
311
|
-
#### Native git hooks
|
|
312
|
-
|
|
313
|
-
```bash
|
|
314
|
-
muaddib init-hooks --type git
|
|
315
|
-
# Creates .git/hooks/pre-commit
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
### Zero-Day Monitor
|
|
319
|
-
|
|
320
|
-
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.
|
|
321
|
-
|
|
322
|
-
### Score breakdown
|
|
323
|
-
|
|
324
|
-
```bash
|
|
325
|
-
muaddib scan . --breakdown
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
Shows explainable score breakdown: how each finding contributes to the final risk score, with per-rule weights and severity multipliers.
|
|
329
|
-
|
|
330
|
-
### Ground truth replay
|
|
331
|
-
|
|
332
|
-
```bash
|
|
333
|
-
muaddib replay
|
|
334
|
-
muaddib ground-truth
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
Replay real-world supply-chain attacks against the scanner to validate detection coverage. Current results: **45/49 detected (91.8% TPR)** from 51 samples (49 active).
|
|
338
|
-
|
|
339
|
-
4 out-of-scope misses: lottie-player, polyfill-io, trojanized-jquery (browser-only DOM attacks), websocket-rat (FP-risky pattern).
|
|
340
|
-
|
|
341
|
-
### Version check
|
|
342
|
-
|
|
343
|
-
MUAD'DIB automatically checks for new versions on startup and notifies you if an update is available.
|
|
344
|
-
|
|
345
|
-
---
|
|
346
|
-
|
|
347
|
-
## Features
|
|
348
|
-
|
|
349
|
-
### Python / PyPI support
|
|
350
|
-
|
|
351
|
-
MUAD'DIB automatically detects and scans Python projects:
|
|
352
|
-
|
|
353
|
-
- **requirements.txt** - All formats including `-r` recursive includes, extras, environment markers
|
|
354
|
-
- **setup.py** - Extracts `install_requires` and `setup_requires`
|
|
355
|
-
- **pyproject.toml** - PEP 621 dependencies and Poetry dependencies
|
|
356
|
-
|
|
357
|
-
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.
|
|
358
|
-
|
|
359
|
-
```
|
|
360
|
-
[PYTHON] Detected Python project (3 dependency files)
|
|
361
|
-
requirements.txt: 12 packages
|
|
362
|
-
setup.py: 3 packages
|
|
363
|
-
pyproject.toml: 8 packages
|
|
364
|
-
|
|
365
|
-
[CRITICAL] PyPI IOC match: malicious-pkg (all versions)
|
|
366
|
-
[HIGH] PyPI typosquat: "reqeusts" looks like "requests"
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
### Typosquatting detection
|
|
370
|
-
|
|
371
|
-
MUAD'DIB detects packages with names similar to popular packages (npm and PyPI):
|
|
372
|
-
|
|
373
|
-
```
|
|
374
|
-
[HIGH] Package "lodahs" looks like "lodash" (swapped_chars). Possible typosquatting.
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
### Dataflow analysis
|
|
378
|
-
|
|
379
|
-
Detects when code reads credentials AND sends them over the network:
|
|
380
|
-
|
|
381
|
-
```
|
|
382
|
-
[CRITICAL] Suspicious flow: credential read (readFileSync, GITHUB_TOKEN) + network send (fetch)
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
### GitHub Actions scanning
|
|
386
|
-
|
|
387
|
-
Detects malicious patterns in `.github/workflows/` YAML files, including Shai-Hulud 2.0 backdoor indicators.
|
|
388
|
-
|
|
389
|
-
### Detected attacks
|
|
390
|
-
|
|
391
|
-
| Campaign | Packages | Status |
|
|
392
|
-
|----------|----------|--------|
|
|
393
|
-
| Shai-Hulud v1 (Sept 2025) | @ctrl/tinycolor, ng2-file-upload | Detected |
|
|
394
|
-
| Shai-Hulud v2 (Nov 2025) | @asyncapi/specs, posthog-node, kill-port | Detected |
|
|
395
|
-
| Shai-Hulud v3 (Dec 2025) | @vietmoney/react-big-calendar | Detected |
|
|
396
|
-
| event-stream (2018) | flatmap-stream, event-stream | Detected |
|
|
397
|
-
| eslint-scope (2018) | eslint-scope | Detected |
|
|
398
|
-
| Protestware | node-ipc, colors, faker | Detected |
|
|
399
|
-
| Typosquats | crossenv, mongose, babelcli | Detected |
|
|
400
|
-
|
|
401
|
-
### Detected techniques
|
|
402
|
-
|
|
403
|
-
| Technique | MITRE | Detection |
|
|
404
|
-
|-----------|-------|-----------|
|
|
405
|
-
| Credential theft (.npmrc, .ssh) | T1552.001 | AST |
|
|
406
|
-
| Env var exfiltration | T1552.001 | AST |
|
|
407
|
-
| Remote code execution | T1105 | Pattern |
|
|
408
|
-
| Reverse shell | T1059.004 | Pattern |
|
|
409
|
-
| Dead man's switch | T1485 | Pattern |
|
|
410
|
-
| Obfuscated code | T1027 | Heuristics |
|
|
411
|
-
| JS obfuscation patterns | T1027.002 | Pattern detection |
|
|
412
|
-
| Shannon entropy (strings) | T1027 | Entropy calculation |
|
|
413
|
-
| Typosquatting (npm + PyPI) | T1195.002 | Levenshtein |
|
|
414
|
-
| Supply chain compromise | T1195.002 | IOC matching |
|
|
415
|
-
| PyPI malicious package | T1195.002 | IOC matching |
|
|
416
|
-
| Sandbox dynamic analysis | Multiple | Docker + strace + tcpdump |
|
|
417
|
-
| Sudden lifecycle script addition | T1195.002 | Temporal analysis |
|
|
418
|
-
| Dangerous API injection between versions | T1195.002 | Temporal AST diff |
|
|
419
|
-
| Publish frequency anomaly | T1195.002 | Registry metadata |
|
|
420
|
-
| Maintainer/publisher change | T1195.002 | Registry metadata |
|
|
421
|
-
| Canary token exfiltration | T1552.001 | Sandbox honey tokens |
|
|
422
|
-
| AI agent weaponization | T1059.004 | AST (s1ngularity/Nx flags) |
|
|
423
|
-
| AI config prompt injection | T1059.004 | File scanning (.cursorrules, CLAUDE.md) |
|
|
424
|
-
| Credential CLI theft (gh, gcloud, aws) | T1552.001 | AST |
|
|
425
|
-
| Binary dropper (chmod + exec /tmp) | T1105 | AST |
|
|
426
|
-
| Prototype hooking (fetch, XMLHttpRequest) | T1557 | AST |
|
|
427
|
-
| Workflow injection (.github/workflows) | T1195.002 | AST |
|
|
428
|
-
| Crypto wallet harvesting | T1005 | Dataflow |
|
|
429
|
-
| Require cache poisoning | T1574.001 | AST |
|
|
430
|
-
| Staged eval decode (eval+atob/Buffer) | T1140 | AST |
|
|
431
|
-
| Deobfuscation (string concat, charcode, base64, hex) | T1140 | AST pre-processing |
|
|
432
|
-
| Cross-file dataflow (inter-module exfiltration) | T1041 | Module graph |
|
|
433
|
-
|
|
434
|
-
---
|
|
435
|
-
|
|
436
|
-
## Supply Chain Anomaly Detection (v2.0)
|
|
437
|
-
|
|
438
|
-
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).
|
|
439
|
-
|
|
440
|
-
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.
|
|
441
|
-
|
|
442
|
-
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.
|
|
443
|
-
|
|
444
|
-
### New features
|
|
445
|
-
|
|
446
|
-
#### 1. Sudden Lifecycle Script Detection (`--temporal`)
|
|
447
|
-
|
|
448
|
-
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.
|
|
449
|
-
|
|
450
|
-
```bash
|
|
451
|
-
muaddib scan . --temporal
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
#### 2. Temporal AST Diff (`--temporal-ast`)
|
|
455
|
-
|
|
456
|
-
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.
|
|
457
|
-
|
|
458
|
-
```bash
|
|
459
|
-
muaddib scan . --temporal-ast
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
#### 3. Publish Frequency Anomaly (`--temporal-publish`)
|
|
463
|
-
|
|
464
|
-
Detects abnormal publishing patterns: burst of versions in 24h, dormant package suddenly updated after 6+ months, rapid version succession (multiple releases in under 1h).
|
|
465
|
-
|
|
466
|
-
```bash
|
|
467
|
-
muaddib scan . --temporal-publish
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
#### 4. Maintainer Change Detection (`--temporal-maintainer`)
|
|
471
|
-
|
|
472
|
-
Detects changes in package maintainers between versions: new maintainer added, sole maintainer replaced (event-stream pattern), suspicious maintainer names, new publisher.
|
|
473
|
-
|
|
474
|
-
```bash
|
|
475
|
-
muaddib scan . --temporal-maintainer
|
|
476
|
-
```
|
|
477
|
-
|
|
478
|
-
#### 5. Canary Tokens / Honey Tokens (sandbox)
|
|
479
|
-
|
|
480
|
-
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.
|
|
481
|
-
|
|
482
|
-
6 honeypot credentials are injected:
|
|
483
|
-
- `GITHUB_TOKEN` / `NPM_TOKEN` — Package registry tokens
|
|
484
|
-
- `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` — Cloud credentials
|
|
485
|
-
- `SLACK_WEBHOOK_URL` / `DISCORD_WEBHOOK_URL` — Messaging webhooks
|
|
486
|
-
|
|
487
|
-
Both dynamic tokens (random per session, from `canary-tokens.js`) and static fallback tokens (in `sandbox-runner.sh`) are used for defense in depth.
|
|
488
|
-
|
|
489
|
-
```bash
|
|
490
|
-
muaddib sandbox suspicious-package
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
### Full temporal scan
|
|
494
|
-
|
|
495
|
-
Enable all temporal analysis features at once:
|
|
496
|
-
|
|
497
|
-
```bash
|
|
498
|
-
muaddib scan . --temporal-full
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
### Usage examples
|
|
502
|
-
|
|
503
|
-
```bash
|
|
504
|
-
# Full behavioral scan (all 5 features)
|
|
505
|
-
muaddib scan . --temporal-full
|
|
506
|
-
|
|
507
|
-
# Only lifecycle script detection
|
|
508
|
-
muaddib scan . --temporal
|
|
509
|
-
|
|
510
|
-
# AST diff + maintainer change
|
|
511
|
-
muaddib scan . --temporal-ast --temporal-maintainer
|
|
512
|
-
|
|
513
|
-
# Sandbox with canary tokens (enabled by default)
|
|
514
|
-
muaddib sandbox suspicious-package
|
|
515
|
-
|
|
516
|
-
# Sandbox without canary tokens
|
|
517
|
-
muaddib sandbox suspicious-package --no-canary
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
### New detection rules (v2.0)
|
|
521
|
-
|
|
522
|
-
| Rule ID | Name | Severity | Feature |
|
|
523
|
-
|---------|------|----------|---------|
|
|
524
|
-
| MUADDIB-TEMPORAL-001 | Sudden Lifecycle Script Added (Critical) | CRITICAL | `--temporal` |
|
|
525
|
-
| MUADDIB-TEMPORAL-002 | Sudden Lifecycle Script Added | HIGH | `--temporal` |
|
|
526
|
-
| MUADDIB-TEMPORAL-003 | Lifecycle Script Modified | MEDIUM | `--temporal` |
|
|
527
|
-
| MUADDIB-TEMPORAL-AST-001 | Dangerous API Added (Critical) | CRITICAL | `--temporal-ast` |
|
|
528
|
-
| MUADDIB-TEMPORAL-AST-002 | Dangerous API Added (High) | HIGH | `--temporal-ast` |
|
|
529
|
-
| MUADDIB-TEMPORAL-AST-003 | Dangerous API Added (Medium) | MEDIUM | `--temporal-ast` |
|
|
530
|
-
| MUADDIB-PUBLISH-001 | Publish Burst Detected | HIGH | `--temporal-publish` |
|
|
531
|
-
| MUADDIB-PUBLISH-002 | Dormant Package Spike | HIGH | `--temporal-publish` |
|
|
532
|
-
| MUADDIB-PUBLISH-003 | Rapid Version Succession | MEDIUM | `--temporal-publish` |
|
|
533
|
-
| MUADDIB-MAINTAINER-001 | New Maintainer Added | HIGH | `--temporal-maintainer` |
|
|
534
|
-
| MUADDIB-MAINTAINER-002 | Suspicious Maintainer Detected | CRITICAL | `--temporal-maintainer` |
|
|
535
|
-
| MUADDIB-MAINTAINER-003 | Sole Maintainer Changed | HIGH | `--temporal-maintainer` |
|
|
536
|
-
| MUADDIB-MAINTAINER-004 | New Publisher Detected | MEDIUM | `--temporal-maintainer` |
|
|
537
|
-
| MUADDIB-CANARY-001 | Canary Token Exfiltration | CRITICAL | sandbox |
|
|
538
|
-
|
|
539
|
-
### Why it matters
|
|
540
|
-
|
|
541
|
-
These features detect attacks like:
|
|
542
|
-
- **Shai-Hulud** (2025): Would be caught by temporal lifecycle + AST diff (sudden `postinstall` + `child_process` added)
|
|
543
|
-
- **ua-parser-js** (2021): Would be caught by maintainer change + lifecycle script detection
|
|
544
|
-
- **event-stream** (2018): Would be caught by sole maintainer change + AST diff (new `flatmap-stream` dependency with `eval`)
|
|
545
|
-
- **coa/rc** (2021): Would be caught by publish burst + lifecycle script detection
|
|
546
|
-
|
|
547
|
-
All without needing a single IOC entry.
|
|
548
|
-
|
|
549
|
-
---
|
|
550
|
-
|
|
551
|
-
## IOC Sources
|
|
552
|
-
|
|
553
|
-
MUAD'DIB aggregates threat intelligence from verified sources only:
|
|
554
|
-
|
|
555
|
-
| Source | Type | Coverage |
|
|
556
|
-
|--------|------|----------|
|
|
557
|
-
| [OSV.dev npm dump](https://osv.dev) | Bulk zip | 200,000+ npm MAL-* entries |
|
|
558
|
-
| [OSV.dev PyPI dump](https://osv.dev) | Bulk zip | 14,000+ PyPI MAL-* entries |
|
|
559
|
-
| [GenSecAI Shai-Hulud Detector](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector) | GitHub | 700+ Shai-Hulud packages |
|
|
560
|
-
| [DataDog Security Labs](https://github.com/DataDog/indicators-of-compromise) | GitHub | Consolidated IOCs from 7 vendors |
|
|
561
|
-
| [OSSF Malicious Packages](https://github.com/ossf/malicious-packages) | OSV API | 8000+ malware reports |
|
|
562
|
-
| [GitHub Advisory](https://github.com/advisories?query=type%3Amalware) | OSV API | Malware-tagged advisories |
|
|
563
|
-
| Snyk Known Malware | Static | Historical attacks |
|
|
564
|
-
| Socket.dev / Phylum | Static | Manual additions |
|
|
565
|
-
|
|
566
|
-
---
|
|
567
|
-
|
|
568
|
-
## VS Code
|
|
569
|
-
|
|
570
|
-
The VS Code extension automatically scans your npm projects.
|
|
571
|
-
|
|
572
|
-
### Installation
|
|
573
|
-
|
|
574
|
-
Search "MUAD'DIB" in VS Code Extensions, or:
|
|
575
|
-
|
|
576
|
-
```bash
|
|
577
|
-
code --install-extension dnszlsk.muaddib-vscode
|
|
578
|
-
```
|
|
579
|
-
|
|
580
|
-
### Commands
|
|
581
|
-
|
|
582
|
-
- `MUAD'DIB: Scan Project` - Scan entire project
|
|
583
|
-
- `MUAD'DIB: Scan Current File` - Scan current file
|
|
584
|
-
|
|
585
|
-
### Settings
|
|
586
|
-
|
|
587
|
-
- `muaddib.autoScan` - Auto-scan on project open (default: true)
|
|
588
|
-
- `muaddib.webhookUrl` - Discord/Slack webhook URL
|
|
589
|
-
- `muaddib.failLevel` - Alert level (critical/high/medium/low)
|
|
590
|
-
|
|
591
|
-
---
|
|
592
|
-
|
|
593
|
-
## CI/CD
|
|
594
|
-
|
|
595
|
-
### GitHub Actions (Marketplace)
|
|
596
|
-
|
|
597
|
-
Use the official MUAD'DIB action from the GitHub Marketplace:
|
|
598
|
-
|
|
599
|
-
```yaml
|
|
600
|
-
name: Security Scan
|
|
601
|
-
|
|
602
|
-
on: [push, pull_request]
|
|
603
|
-
|
|
604
|
-
jobs:
|
|
605
|
-
scan:
|
|
606
|
-
runs-on: ubuntu-latest
|
|
607
|
-
permissions:
|
|
608
|
-
security-events: write
|
|
609
|
-
contents: read
|
|
610
|
-
steps:
|
|
611
|
-
- uses: actions/checkout@v4
|
|
612
|
-
- uses: DNSZLSK/muad-dib@v1
|
|
613
|
-
with:
|
|
614
|
-
path: '.'
|
|
615
|
-
fail-on: 'high'
|
|
616
|
-
sarif: 'results.sarif'
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
#### Action Inputs
|
|
620
|
-
|
|
621
|
-
| Input | Description | Default |
|
|
622
|
-
|-------|-------------|---------|
|
|
623
|
-
| `path` | Path to scan | `.` |
|
|
624
|
-
| `fail-on` | Minimum severity to fail (critical/high/medium/low) | `high` |
|
|
625
|
-
| `sarif` | Path for SARIF output file | `` |
|
|
626
|
-
| `paranoid` | Enable ultra-strict detection | `false` |
|
|
627
|
-
|
|
628
|
-
#### Action Outputs
|
|
629
|
-
|
|
630
|
-
| Output | Description |
|
|
631
|
-
|--------|-------------|
|
|
632
|
-
| `sarif-file` | Path to generated SARIF file |
|
|
633
|
-
| `risk-score` | Risk score (0-100) |
|
|
634
|
-
| `threats-count` | Number of threats detected |
|
|
635
|
-
| `exit-code` | Exit code (0 = clean) |
|
|
636
|
-
|
|
637
|
-
Alerts appear in Security > Code scanning alerts.
|
|
638
|
-
|
|
639
|
-
---
|
|
640
|
-
|
|
641
|
-
## Architecture
|
|
642
|
-
|
|
643
|
-
```
|
|
644
|
-
MUAD'DIB 2.2.
|
|
645
|
-
|
|
|
646
|
-
+-- IOC Match (225,000+ packages, JSON DB)
|
|
647
|
-
| +-- OSV.dev npm dump (200K+ MAL-* entries)
|
|
648
|
-
| +-- OSV.dev PyPI dump (14K+ MAL-* entries)
|
|
649
|
-
| +-- GenSecAI Shai-Hulud Detector
|
|
650
|
-
| +-- DataDog Consolidated IOCs
|
|
651
|
-
| +-- OSSF Malicious Packages (via OSV)
|
|
652
|
-
| +-- GitHub Advisory (malware)
|
|
653
|
-
| +-- Snyk Known Malware
|
|
654
|
-
| +-- Static IOCs (Socket, Phylum)
|
|
655
|
-
|
|
|
656
|
-
+-- Deobfuscation Pre-processing (v2.2.5, --no-deobfuscate to disable)
|
|
657
|
-
| +-- String concat folding, CharCode reconstruction
|
|
658
|
-
| +-- Base64 decode, Hex array resolution
|
|
659
|
-
| +-- Const propagation (Phase 2)
|
|
660
|
-
|
|
|
661
|
-
+-- Inter-module Dataflow (v2.2.6, --no-module-graph to disable)
|
|
662
|
-
| +-- Module dependency graph, tainted export annotation
|
|
663
|
-
| +-- 3-hop re-export chains, class method analysis
|
|
664
|
-
| +-- Cross-file credential read -> network sink detection
|
|
665
|
-
|
|
|
666
|
-
+-- 14 Parallel Scanners (
|
|
667
|
-
| +-- AST Parse (acorn) — eval/Function, credential CLI theft, binary droppers, prototype hooks
|
|
668
|
-
| +-- Pattern Matching (shell, scripts)
|
|
669
|
-
| +-- Obfuscation Detection (skip .min.js, ignore hex/unicode alone)
|
|
670
|
-
| +-- Typosquat Detection (npm + PyPI, Levenshtein)
|
|
671
|
-
| +-- Python Scanner (requirements.txt, setup.py, pyproject.toml)
|
|
672
|
-
| +-- Shannon Entropy (string-level, 5.5 bits + 50 chars min)
|
|
673
|
-
| +-- JS Obfuscation Patterns (_0x* vars, encoded arrays, eval+entropy)
|
|
674
|
-
| +-- GitHub Actions Scanner
|
|
675
|
-
| +-- AI Config Scanner (.cursorrules, CLAUDE.md, copilot-instructions.md)
|
|
676
|
-
| +-- Package, Dependencies, Hash, npm-registry, Dataflow scanners
|
|
677
|
-
|
|
|
678
|
-
+-- Supply Chain Anomaly Detection (v2.0)
|
|
679
|
-
| +-- Temporal Lifecycle Script Detection (--temporal)
|
|
680
|
-
| +-- Temporal AST Diff (--temporal-ast)
|
|
681
|
-
| +-- Publish Frequency Anomaly (--temporal-publish)
|
|
682
|
-
| +-- Maintainer Change Detection (--temporal-maintainer)
|
|
683
|
-
| +-- Canary Tokens / Honey Tokens (sandbox)
|
|
684
|
-
|
|
|
685
|
-
+-- Validation & Observability (v2.1)
|
|
686
|
-
| +-- Ground Truth Dataset (51 real-world attacks, 91.8% TPR)
|
|
687
|
-
| +-- Detection Time Logging (first_seen tracking, lead time metrics)
|
|
688
|
-
| +-- FP Rate Tracking (daily stats, false positive rate)
|
|
689
|
-
| +-- Score Breakdown (explainable per-rule scoring)
|
|
690
|
-
| +-- Threat Feed API (HTTP server, JSON feed for SIEM)
|
|
691
|
-
|
|
|
692
|
-
+-- FP Reduction Post-processing (v2.2.8-v2.2.9)
|
|
693
|
-
| +-- Count-based severity downgrade (dynamic_require, dataflow, etc.)
|
|
694
|
-
| +-- Framework prototype scoring cap
|
|
695
|
-
| +-- Obfuscation in dist/build → LOW
|
|
696
|
-
| +-- Safe env var + prefix filtering
|
|
697
|
-
|
|
|
698
|
-
+-- Per-File Max Scoring (v2.2.11)
|
|
699
|
-
| +-- Score = max(file_scores) + package_level_score
|
|
700
|
-
| +-- Eliminates score accumulation across many files
|
|
701
|
-
| +-- Package-level threats (lifecycle, typosquat, IOC) scored separately
|
|
702
|
-
|
|
|
703
|
-
+-- Paranoid Mode (ultra-strict)
|
|
704
|
-
+-- Docker Sandbox (behavioral analysis, network capture, canary tokens, CI-aware)
|
|
705
|
-
+-- Zero-Day Monitor (internal: npm + PyPI RSS polling, Discord alerts, daily report)
|
|
706
|
-
|
|
|
707
|
-
v
|
|
708
|
-
Dataflow Analysis (credential read -> network send)
|
|
709
|
-
|
|
|
710
|
-
v
|
|
711
|
-
Threat Enrichment (rules, MITRE ATT&CK, playbooks)
|
|
712
|
-
|
|
|
713
|
-
v
|
|
714
|
-
Output (CLI, JSON, HTML, SARIF, Webhook, Threat Feed)
|
|
715
|
-
```
|
|
716
|
-
|
|
717
|
-
---
|
|
718
|
-
|
|
719
|
-
## Evaluation Metrics
|
|
720
|
-
|
|
721
|
-
| Metric | Result | Details |
|
|
722
|
-
|--------|--------|---------|
|
|
723
|
-
| **TPR** (Ground Truth) | **91.8%** (45/49) | 51 real-world attacks (49 active). 4 out-of-scope: browser-only (3) + FP-risky (1) |
|
|
724
|
-
| **FPR** (Standard packages) | **6.2%** (18/290) | Packages with <10 JS files — typical libraries and tools |
|
|
725
|
-
| **FPR** (Benign, global) | **~13%** (69/527) | 529 npm packages, real source code via `npm pack`, threshold > 20 |
|
|
726
|
-
| **ADR** (Adversarial + Holdout) | **100%** (
|
|
727
|
-
|
|
728
|
-
**FPR by package size** — FPR correlates linearly with package size. Per-file max scoring (v2.2.11) significantly reduces FP on medium/large packages:
|
|
729
|
-
|
|
730
|
-
| Category | Packages | FP | FPR |
|
|
731
|
-
|----------|----------|-----|-----|
|
|
732
|
-
| Small (<10 JS files) | 290 | 18 | **6.2%** |
|
|
733
|
-
| Medium (10-50 JS files) | 135 | 16 | 11.9% |
|
|
734
|
-
| Large (50-100 JS files) | 40 | 10 | 25.0% |
|
|
735
|
-
| Very large (100+ JS files) | 62 | 25 | 40.3% |
|
|
736
|
-
|
|
737
|
-
**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)
|
|
738
|
-
|
|
739
|
-
**Holdout progression** (pre-tuning scores, rules frozen):
|
|
740
|
-
|
|
741
|
-
| Holdout | Score | Focus |
|
|
742
|
-
|---------|-------|-------|
|
|
743
|
-
| v1 | 30% (3/10) | General patterns |
|
|
744
|
-
| v2 | 40% (4/10) | Env charcode, lifecycle, prototype |
|
|
745
|
-
| v3 | 60% (6/10) | Require cache, DNS TXT, reverse shell |
|
|
746
|
-
| v4 | **80%** (8/10) | Deobfuscation effectiveness |
|
|
747
|
-
| v5 | 50% (5/10) | Inter-module dataflow (new scanner) |
|
|
748
|
-
|
|
749
|
-
- **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). 4 misses are browser-only (lottie-player, polyfill-io, trojanized-jquery) or risky to fix (websocket-rat) — see [Threat Model](docs/threat-model.md).
|
|
750
|
-
- **FPR** (False Positive Rate): packages scoring > 20 out of 529 real npm packages (source code scanned, not empty dirs). The 6.2% on standard packages (<10 JS files, 290 packages) is the most representative metric for typical use — most npm packages are small.
|
|
751
|
-
- **ADR** (Adversarial Detection Rate): detection rate on 75 evasive malicious samples — 35 adversarial (4 red-team waves) + 40 holdout (5 batches of 10, testing obfuscation, inter-module dataflow, etc.)
|
|
752
|
-
- **Holdout** (pre-tuning): detection rate on 10 unseen samples with rules frozen (measures generalization)
|
|
753
|
-
|
|
754
|
-
Datasets: 529 npm + 132 PyPI benign packages,
|
|
755
|
-
|
|
756
|
-
See [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md) for the full experimental protocol.
|
|
757
|
-
|
|
758
|
-
---
|
|
759
|
-
|
|
760
|
-
## Contributing
|
|
761
|
-
|
|
762
|
-
### Add IOCs
|
|
763
|
-
|
|
764
|
-
Edit YAML files in `iocs/`:
|
|
765
|
-
|
|
766
|
-
```yaml
|
|
767
|
-
- id: NEW-MALWARE-001
|
|
768
|
-
name: "malicious-package"
|
|
769
|
-
version: "*"
|
|
770
|
-
severity: critical
|
|
771
|
-
confidence: high
|
|
772
|
-
source: community
|
|
773
|
-
description: "Threat description"
|
|
774
|
-
references:
|
|
775
|
-
- https://example.com/article
|
|
776
|
-
mitre: T1195.002
|
|
777
|
-
```
|
|
778
|
-
|
|
779
|
-
### Development
|
|
780
|
-
|
|
781
|
-
```bash
|
|
782
|
-
git clone https://github.com/DNSZLSK/muad-dib
|
|
783
|
-
cd muad-dib
|
|
784
|
-
npm install
|
|
785
|
-
npm test
|
|
786
|
-
```
|
|
787
|
-
|
|
788
|
-
### Testing
|
|
789
|
-
|
|
790
|
-
- **
|
|
791
|
-
- **56 fuzz tests** - Malformed YAML, invalid JSON, binary files, ReDoS, unicode, 10MB inputs
|
|
792
|
-
- **
|
|
793
|
-
- **Ground truth validation** - 51 real-world attacks (45/49 detected = 91.8% TPR). 4 out-of-scope: browser-only (3) + FP-risky (1)
|
|
794
|
-
- **False positive validation** - 6.2% FPR on standard packages (18/290), ~13% global (69/527) on real npm source code via `npm pack`
|
|
795
|
-
- **ESLint security audit** - `eslint-plugin-security` with 14 rules enabled
|
|
796
|
-
|
|
797
|
-
---
|
|
798
|
-
|
|
799
|
-
## Community
|
|
800
|
-
|
|
801
|
-
- Discord: https://discord.gg/y8zxSmue
|
|
802
|
-
|
|
803
|
-
---
|
|
804
|
-
|
|
805
|
-
## Documentation
|
|
806
|
-
|
|
807
|
-
- [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md) - Experimental protocol, raw holdout scores, attack sources
|
|
808
|
-
- [Threat Model](docs/threat-model.md) - What MUAD'DIB detects and doesn't detect
|
|
809
|
-
- [Security Audit Report v1.4.1](docs/MUADDIB_Security_Audit_Report_v1.4.1.pdf) - Full security audit (58 issues fixed)
|
|
810
|
-
- [IOCs YAML](iocs/) - Threat database
|
|
811
|
-
|
|
812
|
-
---
|
|
813
|
-
|
|
814
|
-
## License
|
|
815
|
-
|
|
816
|
-
MIT
|
|
817
|
-
|
|
818
|
-
---
|
|
819
|
-
|
|
820
|
-
<p align="center">
|
|
821
|
-
<strong>The spice must flow. The worms must die.</strong>
|
|
822
|
-
</p>
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/muaddibLogo.png" alt="MUAD'DIB Logo" width="700">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/package/muaddib-scanner"><img src="https://img.shields.io/npm/v/muaddib-scanner" alt="npm version"></a>
|
|
7
|
+
<a href="https://github.com/DNSZLSK/muad-dib/actions/workflows/scan.yml"><img src="https://github.com/DNSZLSK/muad-dib/actions/workflows/scan.yml/badge.svg" alt="CI"></a>
|
|
8
|
+
<a href="https://codecov.io/gh/DNSZLSK/muad-dib"><img src="https://codecov.io/gh/DNSZLSK/muad-dib/branch/master/graph/badge.svg" alt="Coverage"></a>
|
|
9
|
+
<a href="https://scorecard.dev/viewer/?uri=github.com/DNSZLSK/muad-dib"><img src="https://api.scorecard.dev/projects/github.com/DNSZLSK/muad-dib/badge" alt="OpenSSF Scorecard"></a>
|
|
10
|
+
<img src="https://img.shields.io/badge/license-MIT-green" alt="License">
|
|
11
|
+
<img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen" alt="Node">
|
|
12
|
+
<img src="https://img.shields.io/badge/IOCs-225%2C000%2B-red" alt="IOCs">
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="#installation">Installation</a> |
|
|
17
|
+
<a href="#usage">Usage</a> |
|
|
18
|
+
<a href="#features">Features</a> |
|
|
19
|
+
<a href="#vs-code">VS Code</a> |
|
|
20
|
+
<a href="#ci-cd">CI/CD</a>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
<p align="center">
|
|
24
|
+
<a href="README.fr.md">Version francaise</a>
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Why MUAD'DIB?
|
|
30
|
+
|
|
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
|
+
|
|
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) + **behavioral anomaly detection** (v2.0) + **ground truth validation** (v2.1) to detect threats AND guide your response — even before they appear in any IOC database.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Positioning
|
|
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.
|
|
40
|
+
|
|
41
|
+
**For enterprise protection**, use:
|
|
42
|
+
- [Socket.dev](https://socket.dev) - ML behavioral analysis, cloud sandboxing
|
|
43
|
+
- [Snyk](https://snyk.io) - Massive vulnerability database, CI/CD integrations
|
|
44
|
+
- [Opengrep](https://opengrep.dev) - Advanced dataflow analysis, Semgrep rules
|
|
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
|
+
---
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
### npm (recommended)
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install -g muaddib-scanner
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### From source
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
git clone https://github.com/DNSZLSK/muad-dib
|
|
62
|
+
cd muad-dib
|
|
63
|
+
npm install
|
|
64
|
+
npm link
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Usage
|
|
70
|
+
|
|
71
|
+
### Basic scan
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
muaddib scan .
|
|
75
|
+
muaddib scan /path/to/project
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Scans both npm (package.json, node_modules) and Python (requirements.txt, setup.py, pyproject.toml) dependencies.
|
|
79
|
+
|
|
80
|
+
### Interactive mode
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
muaddib
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Launches an interactive menu to guide you through all features.
|
|
87
|
+
|
|
88
|
+
### Safe install
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
muaddib install <package>
|
|
92
|
+
muaddib install lodash axios --save-dev
|
|
93
|
+
muaddib i express -g
|
|
94
|
+
muaddib install suspicious-pkg --force # Force install despite threats
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Scans packages for threats BEFORE installing. Blocks known malicious packages.
|
|
98
|
+
|
|
99
|
+
### Risk score
|
|
100
|
+
|
|
101
|
+
Each scan displays a 0-100 risk score:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
[SCORE] 58/100 [***********---------] HIGH
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Explain mode (full details)
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
muaddib scan . --explain
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Shows for each detection:
|
|
114
|
+
- Rule ID
|
|
115
|
+
- MITRE ATT&CK technique
|
|
116
|
+
- References (articles, CVEs)
|
|
117
|
+
- Response playbook
|
|
118
|
+
|
|
119
|
+
### Export
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
muaddib scan . --json > results.json # JSON
|
|
123
|
+
muaddib scan . --html report.html # HTML
|
|
124
|
+
muaddib scan . --sarif results.sarif # SARIF (GitHub Security)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Severity threshold
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
muaddib scan . --fail-on critical # Fail only on CRITICAL
|
|
131
|
+
muaddib scan . --fail-on high # Fail on HIGH and CRITICAL (default)
|
|
132
|
+
muaddib scan . --fail-on medium # Fail on MEDIUM, HIGH, CRITICAL
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Paranoid mode
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
muaddib scan . --paranoid
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Ultra-strict detection with lower tolerance. Useful for critical projects. Detects any network access, subprocess execution, dynamic code evaluation, and sensitive file access.
|
|
142
|
+
|
|
143
|
+
### Discord/Slack webhook
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
muaddib scan . --webhook "https://discord.com/api/webhooks/..."
|
|
147
|
+
```
|
|
148
|
+
|
|
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.
|
|
173
|
+
|
|
174
|
+
### Scrape IOCs (full, ~5 minutes)
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
muaddib scrape
|
|
178
|
+
```
|
|
179
|
+
|
|
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
|
|
191
|
+
|
|
192
|
+
### Docker Sandbox
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
muaddib sandbox <package-name>
|
|
196
|
+
muaddib sandbox <package-name> --strict
|
|
197
|
+
```
|
|
198
|
+
|
|
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
|
+
- **Scoring engine**: 0-100 risk score based on behavioral severity
|
|
209
|
+
|
|
210
|
+
Use `--strict` to block all non-essential outbound network traffic via iptables.
|
|
211
|
+
|
|
212
|
+
Requires Docker Desktop installed.
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
muaddib sandbox lodash # Safe package
|
|
216
|
+
muaddib sandbox suspicious-pkg # Analyze unknown package
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Sandbox network report
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
muaddib sandbox-report <package-name>
|
|
223
|
+
muaddib sandbox-report <package-name> --strict
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Same as `sandbox` but displays a detailed network report: DNS resolutions, HTTP requests, TLS connections, blocked connections (strict mode), and data exfiltration alerts.
|
|
227
|
+
|
|
228
|
+
### Diff (compare versions)
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
muaddib diff <ref> [path]
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Compare threats between the current version and a previous commit/tag. Shows only **NEW** threats introduced since the reference point.
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
muaddib diff HEAD~1 # Compare with previous commit
|
|
238
|
+
muaddib diff v1.2.0 # Compare with tag
|
|
239
|
+
muaddib diff main # Compare with branch
|
|
240
|
+
muaddib diff abc1234 # Compare with specific commit
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Example output:
|
|
244
|
+
```
|
|
245
|
+
[MUADDIB DIFF] Comparing abc1234 -> def5678
|
|
246
|
+
|
|
247
|
+
Risk Score: 25 -> 45 (+20 worse)
|
|
248
|
+
Threats: 3 -> 5
|
|
249
|
+
|
|
250
|
+
NEW threats: 2
|
|
251
|
+
REMOVED threats: 0
|
|
252
|
+
Unchanged: 3
|
|
253
|
+
|
|
254
|
+
NEW THREATS (introduced since v1.2.0)
|
|
255
|
+
------------------------------------
|
|
256
|
+
1. [HIGH] suspicious_dependency
|
|
257
|
+
Known malicious package detected
|
|
258
|
+
File: package.json
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Use in CI to only fail on **new** threats, not existing technical debt:
|
|
262
|
+
```yaml
|
|
263
|
+
- run: muaddib diff ${{ github.event.pull_request.base.sha }} --fail-on high
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Pre-commit hooks
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
muaddib init-hooks [options]
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Automatically scan before each commit. Supports multiple hook systems:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
muaddib init-hooks # Auto-detect (husky/pre-commit/git)
|
|
276
|
+
muaddib init-hooks --type husky # Force husky
|
|
277
|
+
muaddib init-hooks --type pre-commit # Force pre-commit framework
|
|
278
|
+
muaddib init-hooks --type git # Force native git hooks
|
|
279
|
+
muaddib init-hooks --mode diff # Only block NEW threats
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### With pre-commit framework
|
|
283
|
+
|
|
284
|
+
Add to `.pre-commit-config.yaml`:
|
|
285
|
+
```yaml
|
|
286
|
+
repos:
|
|
287
|
+
- repo: https://github.com/DNSZLSK/muad-dib
|
|
288
|
+
rev: v2.2.21
|
|
289
|
+
hooks:
|
|
290
|
+
- id: muaddib-scan # Scan all threats
|
|
291
|
+
# - id: muaddib-diff # Or: only new threats
|
|
292
|
+
# - id: muaddib-paranoid # Or: ultra-strict mode
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
#### With husky
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
npx husky add .husky/pre-commit "npx muaddib scan . --fail-on high"
|
|
299
|
+
# Or for diff mode:
|
|
300
|
+
npx husky add .husky/pre-commit "npx muaddib diff HEAD --fail-on high"
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
#### Remove hooks
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
muaddib remove-hooks [path]
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Removes all MUAD'DIB hooks (husky and git native).
|
|
310
|
+
|
|
311
|
+
#### Native git hooks
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
muaddib init-hooks --type git
|
|
315
|
+
# Creates .git/hooks/pre-commit
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Zero-Day Monitor
|
|
319
|
+
|
|
320
|
+
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.
|
|
321
|
+
|
|
322
|
+
### Score breakdown
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
muaddib scan . --breakdown
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Shows explainable score breakdown: how each finding contributes to the final risk score, with per-rule weights and severity multipliers.
|
|
329
|
+
|
|
330
|
+
### Ground truth replay
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
muaddib replay
|
|
334
|
+
muaddib ground-truth
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Replay real-world supply-chain attacks against the scanner to validate detection coverage. Current results: **45/49 detected (91.8% TPR)** from 51 samples (49 active).
|
|
338
|
+
|
|
339
|
+
4 out-of-scope misses: lottie-player, polyfill-io, trojanized-jquery (browser-only DOM attacks), websocket-rat (FP-risky pattern).
|
|
340
|
+
|
|
341
|
+
### Version check
|
|
342
|
+
|
|
343
|
+
MUAD'DIB automatically checks for new versions on startup and notifies you if an update is available.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Features
|
|
348
|
+
|
|
349
|
+
### Python / PyPI support
|
|
350
|
+
|
|
351
|
+
MUAD'DIB automatically detects and scans Python projects:
|
|
352
|
+
|
|
353
|
+
- **requirements.txt** - All formats including `-r` recursive includes, extras, environment markers
|
|
354
|
+
- **setup.py** - Extracts `install_requires` and `setup_requires`
|
|
355
|
+
- **pyproject.toml** - PEP 621 dependencies and Poetry dependencies
|
|
356
|
+
|
|
357
|
+
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.
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
[PYTHON] Detected Python project (3 dependency files)
|
|
361
|
+
requirements.txt: 12 packages
|
|
362
|
+
setup.py: 3 packages
|
|
363
|
+
pyproject.toml: 8 packages
|
|
364
|
+
|
|
365
|
+
[CRITICAL] PyPI IOC match: malicious-pkg (all versions)
|
|
366
|
+
[HIGH] PyPI typosquat: "reqeusts" looks like "requests"
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Typosquatting detection
|
|
370
|
+
|
|
371
|
+
MUAD'DIB detects packages with names similar to popular packages (npm and PyPI):
|
|
372
|
+
|
|
373
|
+
```
|
|
374
|
+
[HIGH] Package "lodahs" looks like "lodash" (swapped_chars). Possible typosquatting.
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Dataflow analysis
|
|
378
|
+
|
|
379
|
+
Detects when code reads credentials AND sends them over the network:
|
|
380
|
+
|
|
381
|
+
```
|
|
382
|
+
[CRITICAL] Suspicious flow: credential read (readFileSync, GITHUB_TOKEN) + network send (fetch)
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### GitHub Actions scanning
|
|
386
|
+
|
|
387
|
+
Detects malicious patterns in `.github/workflows/` YAML files, including Shai-Hulud 2.0 backdoor indicators.
|
|
388
|
+
|
|
389
|
+
### Detected attacks
|
|
390
|
+
|
|
391
|
+
| Campaign | Packages | Status |
|
|
392
|
+
|----------|----------|--------|
|
|
393
|
+
| Shai-Hulud v1 (Sept 2025) | @ctrl/tinycolor, ng2-file-upload | Detected |
|
|
394
|
+
| Shai-Hulud v2 (Nov 2025) | @asyncapi/specs, posthog-node, kill-port | Detected |
|
|
395
|
+
| Shai-Hulud v3 (Dec 2025) | @vietmoney/react-big-calendar | Detected |
|
|
396
|
+
| event-stream (2018) | flatmap-stream, event-stream | Detected |
|
|
397
|
+
| eslint-scope (2018) | eslint-scope | Detected |
|
|
398
|
+
| Protestware | node-ipc, colors, faker | Detected |
|
|
399
|
+
| Typosquats | crossenv, mongose, babelcli | Detected |
|
|
400
|
+
|
|
401
|
+
### Detected techniques
|
|
402
|
+
|
|
403
|
+
| Technique | MITRE | Detection |
|
|
404
|
+
|-----------|-------|-----------|
|
|
405
|
+
| Credential theft (.npmrc, .ssh) | T1552.001 | AST |
|
|
406
|
+
| Env var exfiltration | T1552.001 | AST |
|
|
407
|
+
| Remote code execution | T1105 | Pattern |
|
|
408
|
+
| Reverse shell | T1059.004 | Pattern |
|
|
409
|
+
| Dead man's switch | T1485 | Pattern |
|
|
410
|
+
| Obfuscated code | T1027 | Heuristics |
|
|
411
|
+
| JS obfuscation patterns | T1027.002 | Pattern detection |
|
|
412
|
+
| Shannon entropy (strings) | T1027 | Entropy calculation |
|
|
413
|
+
| Typosquatting (npm + PyPI) | T1195.002 | Levenshtein |
|
|
414
|
+
| Supply chain compromise | T1195.002 | IOC matching |
|
|
415
|
+
| PyPI malicious package | T1195.002 | IOC matching |
|
|
416
|
+
| Sandbox dynamic analysis | Multiple | Docker + strace + tcpdump |
|
|
417
|
+
| Sudden lifecycle script addition | T1195.002 | Temporal analysis |
|
|
418
|
+
| Dangerous API injection between versions | T1195.002 | Temporal AST diff |
|
|
419
|
+
| Publish frequency anomaly | T1195.002 | Registry metadata |
|
|
420
|
+
| Maintainer/publisher change | T1195.002 | Registry metadata |
|
|
421
|
+
| Canary token exfiltration | T1552.001 | Sandbox honey tokens |
|
|
422
|
+
| AI agent weaponization | T1059.004 | AST (s1ngularity/Nx flags) |
|
|
423
|
+
| AI config prompt injection | T1059.004 | File scanning (.cursorrules, CLAUDE.md) |
|
|
424
|
+
| Credential CLI theft (gh, gcloud, aws) | T1552.001 | AST |
|
|
425
|
+
| Binary dropper (chmod + exec /tmp) | T1105 | AST |
|
|
426
|
+
| Prototype hooking (fetch, XMLHttpRequest) | T1557 | AST |
|
|
427
|
+
| Workflow injection (.github/workflows) | T1195.002 | AST |
|
|
428
|
+
| Crypto wallet harvesting | T1005 | Dataflow |
|
|
429
|
+
| Require cache poisoning | T1574.001 | AST |
|
|
430
|
+
| Staged eval decode (eval+atob/Buffer) | T1140 | AST |
|
|
431
|
+
| Deobfuscation (string concat, charcode, base64, hex) | T1140 | AST pre-processing |
|
|
432
|
+
| Cross-file dataflow (inter-module exfiltration) | T1041 | Module graph |
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## Supply Chain Anomaly Detection (v2.0)
|
|
437
|
+
|
|
438
|
+
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).
|
|
439
|
+
|
|
440
|
+
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.
|
|
441
|
+
|
|
442
|
+
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.
|
|
443
|
+
|
|
444
|
+
### New features
|
|
445
|
+
|
|
446
|
+
#### 1. Sudden Lifecycle Script Detection (`--temporal`)
|
|
447
|
+
|
|
448
|
+
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.
|
|
449
|
+
|
|
450
|
+
```bash
|
|
451
|
+
muaddib scan . --temporal
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
#### 2. Temporal AST Diff (`--temporal-ast`)
|
|
455
|
+
|
|
456
|
+
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.
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
muaddib scan . --temporal-ast
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
#### 3. Publish Frequency Anomaly (`--temporal-publish`)
|
|
463
|
+
|
|
464
|
+
Detects abnormal publishing patterns: burst of versions in 24h, dormant package suddenly updated after 6+ months, rapid version succession (multiple releases in under 1h).
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
muaddib scan . --temporal-publish
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
#### 4. Maintainer Change Detection (`--temporal-maintainer`)
|
|
471
|
+
|
|
472
|
+
Detects changes in package maintainers between versions: new maintainer added, sole maintainer replaced (event-stream pattern), suspicious maintainer names, new publisher.
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
muaddib scan . --temporal-maintainer
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
#### 5. Canary Tokens / Honey Tokens (sandbox)
|
|
479
|
+
|
|
480
|
+
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.
|
|
481
|
+
|
|
482
|
+
6 honeypot credentials are injected:
|
|
483
|
+
- `GITHUB_TOKEN` / `NPM_TOKEN` — Package registry tokens
|
|
484
|
+
- `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` — Cloud credentials
|
|
485
|
+
- `SLACK_WEBHOOK_URL` / `DISCORD_WEBHOOK_URL` — Messaging webhooks
|
|
486
|
+
|
|
487
|
+
Both dynamic tokens (random per session, from `canary-tokens.js`) and static fallback tokens (in `sandbox-runner.sh`) are used for defense in depth.
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
muaddib sandbox suspicious-package
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### Full temporal scan
|
|
494
|
+
|
|
495
|
+
Enable all temporal analysis features at once:
|
|
496
|
+
|
|
497
|
+
```bash
|
|
498
|
+
muaddib scan . --temporal-full
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
### Usage examples
|
|
502
|
+
|
|
503
|
+
```bash
|
|
504
|
+
# Full behavioral scan (all 5 features)
|
|
505
|
+
muaddib scan . --temporal-full
|
|
506
|
+
|
|
507
|
+
# Only lifecycle script detection
|
|
508
|
+
muaddib scan . --temporal
|
|
509
|
+
|
|
510
|
+
# AST diff + maintainer change
|
|
511
|
+
muaddib scan . --temporal-ast --temporal-maintainer
|
|
512
|
+
|
|
513
|
+
# Sandbox with canary tokens (enabled by default)
|
|
514
|
+
muaddib sandbox suspicious-package
|
|
515
|
+
|
|
516
|
+
# Sandbox without canary tokens
|
|
517
|
+
muaddib sandbox suspicious-package --no-canary
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### New detection rules (v2.0)
|
|
521
|
+
|
|
522
|
+
| Rule ID | Name | Severity | Feature |
|
|
523
|
+
|---------|------|----------|---------|
|
|
524
|
+
| MUADDIB-TEMPORAL-001 | Sudden Lifecycle Script Added (Critical) | CRITICAL | `--temporal` |
|
|
525
|
+
| MUADDIB-TEMPORAL-002 | Sudden Lifecycle Script Added | HIGH | `--temporal` |
|
|
526
|
+
| MUADDIB-TEMPORAL-003 | Lifecycle Script Modified | MEDIUM | `--temporal` |
|
|
527
|
+
| MUADDIB-TEMPORAL-AST-001 | Dangerous API Added (Critical) | CRITICAL | `--temporal-ast` |
|
|
528
|
+
| MUADDIB-TEMPORAL-AST-002 | Dangerous API Added (High) | HIGH | `--temporal-ast` |
|
|
529
|
+
| MUADDIB-TEMPORAL-AST-003 | Dangerous API Added (Medium) | MEDIUM | `--temporal-ast` |
|
|
530
|
+
| MUADDIB-PUBLISH-001 | Publish Burst Detected | HIGH | `--temporal-publish` |
|
|
531
|
+
| MUADDIB-PUBLISH-002 | Dormant Package Spike | HIGH | `--temporal-publish` |
|
|
532
|
+
| MUADDIB-PUBLISH-003 | Rapid Version Succession | MEDIUM | `--temporal-publish` |
|
|
533
|
+
| MUADDIB-MAINTAINER-001 | New Maintainer Added | HIGH | `--temporal-maintainer` |
|
|
534
|
+
| MUADDIB-MAINTAINER-002 | Suspicious Maintainer Detected | CRITICAL | `--temporal-maintainer` |
|
|
535
|
+
| MUADDIB-MAINTAINER-003 | Sole Maintainer Changed | HIGH | `--temporal-maintainer` |
|
|
536
|
+
| MUADDIB-MAINTAINER-004 | New Publisher Detected | MEDIUM | `--temporal-maintainer` |
|
|
537
|
+
| MUADDIB-CANARY-001 | Canary Token Exfiltration | CRITICAL | sandbox |
|
|
538
|
+
|
|
539
|
+
### Why it matters
|
|
540
|
+
|
|
541
|
+
These features detect attacks like:
|
|
542
|
+
- **Shai-Hulud** (2025): Would be caught by temporal lifecycle + AST diff (sudden `postinstall` + `child_process` added)
|
|
543
|
+
- **ua-parser-js** (2021): Would be caught by maintainer change + lifecycle script detection
|
|
544
|
+
- **event-stream** (2018): Would be caught by sole maintainer change + AST diff (new `flatmap-stream` dependency with `eval`)
|
|
545
|
+
- **coa/rc** (2021): Would be caught by publish burst + lifecycle script detection
|
|
546
|
+
|
|
547
|
+
All without needing a single IOC entry.
|
|
548
|
+
|
|
549
|
+
---
|
|
550
|
+
|
|
551
|
+
## IOC Sources
|
|
552
|
+
|
|
553
|
+
MUAD'DIB aggregates threat intelligence from verified sources only:
|
|
554
|
+
|
|
555
|
+
| Source | Type | Coverage |
|
|
556
|
+
|--------|------|----------|
|
|
557
|
+
| [OSV.dev npm dump](https://osv.dev) | Bulk zip | 200,000+ npm MAL-* entries |
|
|
558
|
+
| [OSV.dev PyPI dump](https://osv.dev) | Bulk zip | 14,000+ PyPI MAL-* entries |
|
|
559
|
+
| [GenSecAI Shai-Hulud Detector](https://github.com/gensecaihq/Shai-Hulud-2.0-Detector) | GitHub | 700+ Shai-Hulud packages |
|
|
560
|
+
| [DataDog Security Labs](https://github.com/DataDog/indicators-of-compromise) | GitHub | Consolidated IOCs from 7 vendors |
|
|
561
|
+
| [OSSF Malicious Packages](https://github.com/ossf/malicious-packages) | OSV API | 8000+ malware reports |
|
|
562
|
+
| [GitHub Advisory](https://github.com/advisories?query=type%3Amalware) | OSV API | Malware-tagged advisories |
|
|
563
|
+
| Snyk Known Malware | Static | Historical attacks |
|
|
564
|
+
| Socket.dev / Phylum | Static | Manual additions |
|
|
565
|
+
|
|
566
|
+
---
|
|
567
|
+
|
|
568
|
+
## VS Code
|
|
569
|
+
|
|
570
|
+
The VS Code extension automatically scans your npm projects.
|
|
571
|
+
|
|
572
|
+
### Installation
|
|
573
|
+
|
|
574
|
+
Search "MUAD'DIB" in VS Code Extensions, or:
|
|
575
|
+
|
|
576
|
+
```bash
|
|
577
|
+
code --install-extension dnszlsk.muaddib-vscode
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### Commands
|
|
581
|
+
|
|
582
|
+
- `MUAD'DIB: Scan Project` - Scan entire project
|
|
583
|
+
- `MUAD'DIB: Scan Current File` - Scan current file
|
|
584
|
+
|
|
585
|
+
### Settings
|
|
586
|
+
|
|
587
|
+
- `muaddib.autoScan` - Auto-scan on project open (default: true)
|
|
588
|
+
- `muaddib.webhookUrl` - Discord/Slack webhook URL
|
|
589
|
+
- `muaddib.failLevel` - Alert level (critical/high/medium/low)
|
|
590
|
+
|
|
591
|
+
---
|
|
592
|
+
|
|
593
|
+
## CI/CD
|
|
594
|
+
|
|
595
|
+
### GitHub Actions (Marketplace)
|
|
596
|
+
|
|
597
|
+
Use the official MUAD'DIB action from the GitHub Marketplace:
|
|
598
|
+
|
|
599
|
+
```yaml
|
|
600
|
+
name: Security Scan
|
|
601
|
+
|
|
602
|
+
on: [push, pull_request]
|
|
603
|
+
|
|
604
|
+
jobs:
|
|
605
|
+
scan:
|
|
606
|
+
runs-on: ubuntu-latest
|
|
607
|
+
permissions:
|
|
608
|
+
security-events: write
|
|
609
|
+
contents: read
|
|
610
|
+
steps:
|
|
611
|
+
- uses: actions/checkout@v4
|
|
612
|
+
- uses: DNSZLSK/muad-dib@v1
|
|
613
|
+
with:
|
|
614
|
+
path: '.'
|
|
615
|
+
fail-on: 'high'
|
|
616
|
+
sarif: 'results.sarif'
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
#### Action Inputs
|
|
620
|
+
|
|
621
|
+
| Input | Description | Default |
|
|
622
|
+
|-------|-------------|---------|
|
|
623
|
+
| `path` | Path to scan | `.` |
|
|
624
|
+
| `fail-on` | Minimum severity to fail (critical/high/medium/low) | `high` |
|
|
625
|
+
| `sarif` | Path for SARIF output file | `` |
|
|
626
|
+
| `paranoid` | Enable ultra-strict detection | `false` |
|
|
627
|
+
|
|
628
|
+
#### Action Outputs
|
|
629
|
+
|
|
630
|
+
| Output | Description |
|
|
631
|
+
|--------|-------------|
|
|
632
|
+
| `sarif-file` | Path to generated SARIF file |
|
|
633
|
+
| `risk-score` | Risk score (0-100) |
|
|
634
|
+
| `threats-count` | Number of threats detected |
|
|
635
|
+
| `exit-code` | Exit code (0 = clean) |
|
|
636
|
+
|
|
637
|
+
Alerts appear in Security > Code scanning alerts.
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
## Architecture
|
|
642
|
+
|
|
643
|
+
```
|
|
644
|
+
MUAD'DIB 2.2.21 Scanner
|
|
645
|
+
|
|
|
646
|
+
+-- IOC Match (225,000+ packages, JSON DB)
|
|
647
|
+
| +-- OSV.dev npm dump (200K+ MAL-* entries)
|
|
648
|
+
| +-- OSV.dev PyPI dump (14K+ MAL-* entries)
|
|
649
|
+
| +-- GenSecAI Shai-Hulud Detector
|
|
650
|
+
| +-- DataDog Consolidated IOCs
|
|
651
|
+
| +-- OSSF Malicious Packages (via OSV)
|
|
652
|
+
| +-- GitHub Advisory (malware)
|
|
653
|
+
| +-- Snyk Known Malware
|
|
654
|
+
| +-- Static IOCs (Socket, Phylum)
|
|
655
|
+
|
|
|
656
|
+
+-- Deobfuscation Pre-processing (v2.2.5, --no-deobfuscate to disable)
|
|
657
|
+
| +-- String concat folding, CharCode reconstruction
|
|
658
|
+
| +-- Base64 decode, Hex array resolution
|
|
659
|
+
| +-- Const propagation (Phase 2)
|
|
660
|
+
|
|
|
661
|
+
+-- Inter-module Dataflow (v2.2.6, --no-module-graph to disable)
|
|
662
|
+
| +-- Module dependency graph, tainted export annotation
|
|
663
|
+
| +-- 3-hop re-export chains, class method analysis
|
|
664
|
+
| +-- Cross-file credential read -> network sink detection
|
|
665
|
+
|
|
|
666
|
+
+-- 14 Parallel Scanners (94 rules)
|
|
667
|
+
| +-- AST Parse (acorn) — eval/Function, credential CLI theft, binary droppers, prototype hooks
|
|
668
|
+
| +-- Pattern Matching (shell, scripts)
|
|
669
|
+
| +-- Obfuscation Detection (skip .min.js, ignore hex/unicode alone)
|
|
670
|
+
| +-- Typosquat Detection (npm + PyPI, Levenshtein)
|
|
671
|
+
| +-- Python Scanner (requirements.txt, setup.py, pyproject.toml)
|
|
672
|
+
| +-- Shannon Entropy (string-level, 5.5 bits + 50 chars min)
|
|
673
|
+
| +-- JS Obfuscation Patterns (_0x* vars, encoded arrays, eval+entropy)
|
|
674
|
+
| +-- GitHub Actions Scanner
|
|
675
|
+
| +-- AI Config Scanner (.cursorrules, CLAUDE.md, copilot-instructions.md)
|
|
676
|
+
| +-- Package, Dependencies, Hash, npm-registry, Dataflow scanners
|
|
677
|
+
|
|
|
678
|
+
+-- Supply Chain Anomaly Detection (v2.0)
|
|
679
|
+
| +-- Temporal Lifecycle Script Detection (--temporal)
|
|
680
|
+
| +-- Temporal AST Diff (--temporal-ast)
|
|
681
|
+
| +-- Publish Frequency Anomaly (--temporal-publish)
|
|
682
|
+
| +-- Maintainer Change Detection (--temporal-maintainer)
|
|
683
|
+
| +-- Canary Tokens / Honey Tokens (sandbox)
|
|
684
|
+
|
|
|
685
|
+
+-- Validation & Observability (v2.1)
|
|
686
|
+
| +-- Ground Truth Dataset (51 real-world attacks, 91.8% TPR)
|
|
687
|
+
| +-- Detection Time Logging (first_seen tracking, lead time metrics)
|
|
688
|
+
| +-- FP Rate Tracking (daily stats, false positive rate)
|
|
689
|
+
| +-- Score Breakdown (explainable per-rule scoring)
|
|
690
|
+
| +-- Threat Feed API (HTTP server, JSON feed for SIEM)
|
|
691
|
+
|
|
|
692
|
+
+-- FP Reduction Post-processing (v2.2.8-v2.2.9)
|
|
693
|
+
| +-- Count-based severity downgrade (dynamic_require, dataflow, etc.)
|
|
694
|
+
| +-- Framework prototype scoring cap
|
|
695
|
+
| +-- Obfuscation in dist/build → LOW
|
|
696
|
+
| +-- Safe env var + prefix filtering
|
|
697
|
+
|
|
|
698
|
+
+-- Per-File Max Scoring (v2.2.11)
|
|
699
|
+
| +-- Score = max(file_scores) + package_level_score
|
|
700
|
+
| +-- Eliminates score accumulation across many files
|
|
701
|
+
| +-- Package-level threats (lifecycle, typosquat, IOC) scored separately
|
|
702
|
+
|
|
|
703
|
+
+-- Paranoid Mode (ultra-strict)
|
|
704
|
+
+-- Docker Sandbox (behavioral analysis, network capture, canary tokens, CI-aware)
|
|
705
|
+
+-- Zero-Day Monitor (internal: npm + PyPI RSS polling, Discord alerts, daily report)
|
|
706
|
+
|
|
|
707
|
+
v
|
|
708
|
+
Dataflow Analysis (credential read -> network send)
|
|
709
|
+
|
|
|
710
|
+
v
|
|
711
|
+
Threat Enrichment (rules, MITRE ATT&CK, playbooks)
|
|
712
|
+
|
|
|
713
|
+
v
|
|
714
|
+
Output (CLI, JSON, HTML, SARIF, Webhook, Threat Feed)
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
---
|
|
718
|
+
|
|
719
|
+
## Evaluation Metrics
|
|
720
|
+
|
|
721
|
+
| Metric | Result | Details |
|
|
722
|
+
|--------|--------|---------|
|
|
723
|
+
| **TPR** (Ground Truth) | **91.8%** (45/49) | 51 real-world attacks (49 active). 4 out-of-scope: browser-only (3) + FP-risky (1) |
|
|
724
|
+
| **FPR** (Standard packages) | **6.2%** (18/290) | Packages with <10 JS files — typical libraries and tools |
|
|
725
|
+
| **FPR** (Benign, global) | **~13%** (69/527) | 529 npm packages, real source code via `npm pack`, threshold > 20 |
|
|
726
|
+
| **ADR** (Adversarial + Holdout) | **100%** (78/78) | 38 adversarial + 40 holdout evasive samples across 5 red-team waves |
|
|
727
|
+
|
|
728
|
+
**FPR by package size** — FPR correlates linearly with package size. Per-file max scoring (v2.2.11) significantly reduces FP on medium/large packages:
|
|
729
|
+
|
|
730
|
+
| Category | Packages | FP | FPR |
|
|
731
|
+
|----------|----------|-----|-----|
|
|
732
|
+
| Small (<10 JS files) | 290 | 18 | **6.2%** |
|
|
733
|
+
| Medium (10-50 JS files) | 135 | 16 | 11.9% |
|
|
734
|
+
| Large (50-100 JS files) | 40 | 10 | 25.0% |
|
|
735
|
+
| Very large (100+ JS files) | 62 | 25 | 40.3% |
|
|
736
|
+
|
|
737
|
+
**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)
|
|
738
|
+
|
|
739
|
+
**Holdout progression** (pre-tuning scores, rules frozen):
|
|
740
|
+
|
|
741
|
+
| Holdout | Score | Focus |
|
|
742
|
+
|---------|-------|-------|
|
|
743
|
+
| v1 | 30% (3/10) | General patterns |
|
|
744
|
+
| v2 | 40% (4/10) | Env charcode, lifecycle, prototype |
|
|
745
|
+
| v3 | 60% (6/10) | Require cache, DNS TXT, reverse shell |
|
|
746
|
+
| v4 | **80%** (8/10) | Deobfuscation effectiveness |
|
|
747
|
+
| v5 | 50% (5/10) | Inter-module dataflow (new scanner) |
|
|
748
|
+
|
|
749
|
+
- **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). 4 misses are browser-only (lottie-player, polyfill-io, trojanized-jquery) or risky to fix (websocket-rat) — see [Threat Model](docs/threat-model.md).
|
|
750
|
+
- **FPR** (False Positive Rate): packages scoring > 20 out of 529 real npm packages (source code scanned, not empty dirs). The 6.2% on standard packages (<10 JS files, 290 packages) is the most representative metric for typical use — most npm packages are small.
|
|
751
|
+
- **ADR** (Adversarial Detection Rate): detection rate on 75 evasive malicious samples — 35 adversarial (4 red-team waves) + 40 holdout (5 batches of 10, testing obfuscation, inter-module dataflow, etc.)
|
|
752
|
+
- **Holdout** (pre-tuning): detection rate on 10 unseen samples with rules frozen (measures generalization)
|
|
753
|
+
|
|
754
|
+
Datasets: 529 npm + 132 PyPI benign packages, 78 adversarial/holdout samples, 51 ground-truth attacks (65 documented malware packages).
|
|
755
|
+
|
|
756
|
+
See [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md) for the full experimental protocol.
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
## Contributing
|
|
761
|
+
|
|
762
|
+
### Add IOCs
|
|
763
|
+
|
|
764
|
+
Edit YAML files in `iocs/`:
|
|
765
|
+
|
|
766
|
+
```yaml
|
|
767
|
+
- id: NEW-MALWARE-001
|
|
768
|
+
name: "malicious-package"
|
|
769
|
+
version: "*"
|
|
770
|
+
severity: critical
|
|
771
|
+
confidence: high
|
|
772
|
+
source: community
|
|
773
|
+
description: "Threat description"
|
|
774
|
+
references:
|
|
775
|
+
- https://example.com/article
|
|
776
|
+
mitre: T1195.002
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### Development
|
|
780
|
+
|
|
781
|
+
```bash
|
|
782
|
+
git clone https://github.com/DNSZLSK/muad-dib
|
|
783
|
+
cd muad-dib
|
|
784
|
+
npm install
|
|
785
|
+
npm test
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
### Testing
|
|
789
|
+
|
|
790
|
+
- **862 unit/integration tests** across 20 modular test files - 74% code coverage via [Codecov](https://codecov.io/gh/DNSZLSK/muad-dib)
|
|
791
|
+
- **56 fuzz tests** - Malformed YAML, invalid JSON, binary files, ReDoS, unicode, 10MB inputs
|
|
792
|
+
- **78 adversarial/holdout samples** - 38 adversarial + 40 holdout, 78/78 detection rate (100% ADR)
|
|
793
|
+
- **Ground truth validation** - 51 real-world attacks (45/49 detected = 91.8% TPR). 4 out-of-scope: browser-only (3) + FP-risky (1)
|
|
794
|
+
- **False positive validation** - 6.2% FPR on standard packages (18/290), ~13% global (69/527) on real npm source code via `npm pack`
|
|
795
|
+
- **ESLint security audit** - `eslint-plugin-security` with 14 rules enabled
|
|
796
|
+
|
|
797
|
+
---
|
|
798
|
+
|
|
799
|
+
## Community
|
|
800
|
+
|
|
801
|
+
- Discord: https://discord.gg/y8zxSmue
|
|
802
|
+
|
|
803
|
+
---
|
|
804
|
+
|
|
805
|
+
## Documentation
|
|
806
|
+
|
|
807
|
+
- [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md) - Experimental protocol, raw holdout scores, attack sources
|
|
808
|
+
- [Threat Model](docs/threat-model.md) - What MUAD'DIB detects and doesn't detect
|
|
809
|
+
- [Security Audit Report v1.4.1](docs/MUADDIB_Security_Audit_Report_v1.4.1.pdf) - Full security audit (58 issues fixed)
|
|
810
|
+
- [IOCs YAML](iocs/) - Threat database
|
|
811
|
+
|
|
812
|
+
---
|
|
813
|
+
|
|
814
|
+
## License
|
|
815
|
+
|
|
816
|
+
MIT
|
|
817
|
+
|
|
818
|
+
---
|
|
819
|
+
|
|
820
|
+
<p align="center">
|
|
821
|
+
<strong>The spice must flow. The worms must die.</strong>
|
|
822
|
+
</p>
|