muaddib-scanner 2.10.23 → 2.10.27
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/bin/muaddib.js +2 -541
- package/package.json +1 -1
- package/src/canary-tokens.js +2 -256
- package/src/commands/diff.js +411 -0
- package/src/commands/help.js +356 -0
- package/src/commands/hooks-init.js +264 -0
- package/src/commands/interactive.js +200 -0
- package/src/commands/safe-install.js +294 -0
- package/src/diff.js +2 -411
- package/src/hooks-init.js +2 -264
- package/src/index.js +20 -861
- package/src/integrations/canary-tokens.js +256 -0
- package/src/integrations/maintainer-change.js +224 -0
- package/src/integrations/publish-anomaly.js +206 -0
- package/src/integrations/threat-feed.js +95 -0
- package/src/integrations/webhook.js +445 -0
- package/src/maintainer-change.js +2 -224
- package/src/ml/jsonl-writer.js +2 -1
- package/src/monitor/classify.js +355 -0
- package/src/monitor/daemon.js +200 -0
- package/src/monitor/healthcheck.js +147 -0
- package/src/monitor/ingestion.js +605 -0
- package/src/monitor/queue.js +994 -0
- package/src/monitor/state.js +881 -0
- package/src/monitor/temporal.js +433 -0
- package/src/monitor/webhook.js +1055 -0
- package/src/output/formatter.js +192 -0
- package/src/output/report.js +230 -0
- package/src/output/sarif.js +102 -0
- package/src/output-formatter.js +2 -192
- package/src/pipeline/executor.js +295 -0
- package/src/pipeline/initializer.js +62 -0
- package/src/pipeline/outputter.js +51 -0
- package/src/pipeline/processor.js +300 -0
- package/src/pipeline/scan-worker.js +31 -0
- package/src/publish-anomaly.js +2 -206
- package/src/report.js +2 -230
- package/src/runtime/daemon.js +178 -0
- package/src/runtime/serve.js +126 -0
- package/src/runtime/watch.js +56 -0
- package/src/safe-install.js +2 -294
- package/src/sarif.js +2 -102
- package/src/scan-context.js +31 -0
- package/src/scan-worker.js +2 -31
- package/src/scanner/ast-detectors/constants.js +247 -0
- package/src/scanner/ast-detectors/handle-assignment-expression.js +285 -0
- package/src/scanner/ast-detectors/handle-call-expression.js +1822 -0
- package/src/scanner/ast-detectors/handle-import-expression.js +46 -0
- package/src/scanner/ast-detectors/handle-literal.js +118 -0
- package/src/scanner/ast-detectors/handle-member-expression.js +80 -0
- package/src/scanner/ast-detectors/handle-new-expression.js +180 -0
- package/src/scanner/ast-detectors/handle-post-walk.js +494 -0
- package/src/scanner/ast-detectors/handle-variable-declarator.js +376 -0
- package/src/scanner/ast-detectors/handle-with-statement.js +55 -0
- package/src/scanner/ast-detectors/helpers.js +261 -0
- package/src/scanner/ast-detectors/index.js +23 -0
- package/src/scanner/ast.js +1 -1
- package/src/scanner/module-graph/annotate-sinks.js +188 -0
- package/src/scanner/module-graph/annotate-tainted.js +369 -0
- package/src/scanner/module-graph/build-graph.js +119 -0
- package/src/scanner/module-graph/constants.js +33 -0
- package/src/scanner/module-graph/detect-callback-flows.js +129 -0
- package/src/scanner/module-graph/detect-cross-file.js +957 -0
- package/src/scanner/module-graph/detect-event-flows.js +213 -0
- package/src/scanner/module-graph/index.js +18 -0
- package/src/scanner/module-graph/parse-utils.js +142 -0
- package/src/scanner/paranoid.js +230 -0
- package/src/scanner/reachability.js +1 -1
- package/src/scanner/temporal-analysis.js +349 -0
- package/src/scanner/temporal-ast-diff.js +334 -0
- package/src/scanner/temporal-runner.js +163 -0
- package/src/temporal-analysis.js +2 -349
- package/src/temporal-ast-diff.js +2 -334
- package/src/temporal-runner.js +2 -163
- package/src/watch.js +2 -56
- package/src/webhook.js +2 -445
- package/scripts/fix-permissions.sh +0 -24
- package/src/scanner/ast-detectors.js +0 -3797
- package/src/scanner/module-graph.js +0 -2096
package/bin/muaddib.js
CHANGED
|
@@ -30,6 +30,8 @@ const { safeInstall } = require('../src/safe-install.js');
|
|
|
30
30
|
const { buildSandboxImage, runSandbox, generateNetworkReport } = require('../src/sandbox/index.js');
|
|
31
31
|
const { diff, showRefs } = require('../src/diff.js');
|
|
32
32
|
const { initHooks, removeHooks } = require('../src/hooks-init.js');
|
|
33
|
+
const { showHelp, commandHelp } = require('../src/commands/help.js');
|
|
34
|
+
const { interactiveMenu } = require('../src/commands/interactive.js');
|
|
33
35
|
|
|
34
36
|
const args = process.argv.slice(2);
|
|
35
37
|
const command = args[0];
|
|
@@ -221,547 +223,6 @@ if (!jsonOutput && !sarifOutput && command !== 'feed' && command !== 'serve') {
|
|
|
221
223
|
}
|
|
222
224
|
}
|
|
223
225
|
|
|
224
|
-
// Interactive menu
|
|
225
|
-
async function interactiveMenu() {
|
|
226
|
-
const { select, input, confirm } = await import('@inquirer/prompts');
|
|
227
|
-
|
|
228
|
-
console.log(`
|
|
229
|
-
╔═══════════════════════════════════════════════╗
|
|
230
|
-
║ MUAD'DIB - npm & PyPI Supply Chain Hunter ║
|
|
231
|
-
║ "The worms must die." ║
|
|
232
|
-
╚═══════════════════════════════════════════════╝
|
|
233
|
-
`);
|
|
234
|
-
|
|
235
|
-
const action = await select({
|
|
236
|
-
message: 'What do you want to do?',
|
|
237
|
-
choices: [
|
|
238
|
-
{ name: 'Scan a project', value: 'scan' },
|
|
239
|
-
{ name: 'Scan with paranoid mode', value: 'scan-paranoid' },
|
|
240
|
-
{ name: 'Compare with previous version (diff)', value: 'diff' },
|
|
241
|
-
{ name: 'Install packages (safe)', value: 'install' },
|
|
242
|
-
{ name: 'Watch a project (real-time)', value: 'watch' },
|
|
243
|
-
{ name: 'Start daemon', value: 'daemon' },
|
|
244
|
-
{ name: 'Setup git hooks', value: 'init-hooks' },
|
|
245
|
-
{ name: 'Update IOCs', value: 'update' },
|
|
246
|
-
{ name: 'Scrape new IOCs', value: 'scrape' },
|
|
247
|
-
{ name: 'Sandbox analysis', value: 'sandbox' },
|
|
248
|
-
{ name: 'Threat feed (JSON)', value: 'feed' },
|
|
249
|
-
{ name: 'Threat feed server', value: 'serve' },
|
|
250
|
-
{ name: 'Quit', value: 'quit' }
|
|
251
|
-
]
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
if (action === 'quit') {
|
|
255
|
-
console.log('Bye!');
|
|
256
|
-
process.exit(0);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (action === 'scan' || action === 'scan-paranoid') {
|
|
260
|
-
const path = await input({
|
|
261
|
-
message: 'Project path:',
|
|
262
|
-
default: '.'
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
const outputFormat = await select({
|
|
266
|
-
message: 'Output format:',
|
|
267
|
-
choices: [
|
|
268
|
-
{ name: 'Console (default)', value: 'console' },
|
|
269
|
-
{ name: 'JSON', value: 'json' },
|
|
270
|
-
{ name: 'HTML', value: 'html' },
|
|
271
|
-
{ name: 'SARIF (GitHub Security)', value: 'sarif' }
|
|
272
|
-
]
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
const opts = {
|
|
276
|
-
json: outputFormat === 'json',
|
|
277
|
-
html: outputFormat === 'html' ? 'muaddib-report.html' : null,
|
|
278
|
-
sarif: outputFormat === 'sarif' ? 'muaddib-results.sarif' : null,
|
|
279
|
-
explain: true,
|
|
280
|
-
failLevel: 'high',
|
|
281
|
-
paranoid: action === 'scan-paranoid'
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
const exitCode = await run(path, opts);
|
|
285
|
-
process.exit(exitCode);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (action === 'install') {
|
|
289
|
-
const pkgInput = await input({
|
|
290
|
-
message: 'Package(s) to install (space-separated):'
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
const packages = pkgInput.split(' ').filter(p => p.trim());
|
|
294
|
-
if (packages.length === 0) {
|
|
295
|
-
console.log('No packages specified.');
|
|
296
|
-
process.exit(1);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const result = await safeInstall(packages, {});
|
|
300
|
-
process.exit(result.blocked ? 1 : 0);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
if (action === 'watch') {
|
|
304
|
-
const path = await input({
|
|
305
|
-
message: 'Project path:',
|
|
306
|
-
default: '.'
|
|
307
|
-
});
|
|
308
|
-
watch(path);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (action === 'daemon') {
|
|
312
|
-
const useWebhook = await confirm({
|
|
313
|
-
message: 'Configure Discord/Slack webhook?',
|
|
314
|
-
default: false
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
let webhook = null;
|
|
318
|
-
if (useWebhook) {
|
|
319
|
-
webhook = await input({
|
|
320
|
-
message: 'Webhook URL:'
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
const { startDaemon } = require('../src/daemon.js');
|
|
324
|
-
startDaemon({ webhook });
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
if (action === 'update') {
|
|
328
|
-
await updateIOCs();
|
|
329
|
-
process.exit(0);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
if (action === 'scrape') {
|
|
333
|
-
const result = await runScraper();
|
|
334
|
-
console.log(`[OK] ${result.added} new IOCs (total: ${result.total})`);
|
|
335
|
-
process.exit(0);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
if (action === 'sandbox') {
|
|
339
|
-
const packageName = await input({
|
|
340
|
-
message: 'Package name to analyze:'
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
if (!packageName.trim()) {
|
|
344
|
-
console.log('No package specified.');
|
|
345
|
-
process.exit(1);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
const useStrict = await confirm({
|
|
349
|
-
message: 'Enable strict mode? (blocks non-essential network)',
|
|
350
|
-
default: false
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
await buildSandboxImage();
|
|
354
|
-
const results = await runSandbox(packageName.trim(), { strict: useStrict });
|
|
355
|
-
if (results.raw_report) {
|
|
356
|
-
console.log(generateNetworkReport(results.raw_report));
|
|
357
|
-
}
|
|
358
|
-
process.exit(results.suspicious ? 1 : 0);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
if (action === 'feed') {
|
|
362
|
-
const { getFeed } = require('../src/threat-feed.js');
|
|
363
|
-
const result = getFeed();
|
|
364
|
-
console.log(JSON.stringify(result, null, 2));
|
|
365
|
-
process.exit(0);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
if (action === 'serve') {
|
|
369
|
-
const { startServer } = require('../src/serve.js');
|
|
370
|
-
startServer({ port: 3000 });
|
|
371
|
-
// Server runs indefinitely
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
if (action === 'diff') {
|
|
375
|
-
const baseRef = await input({
|
|
376
|
-
message: 'Compare with (commit/tag/branch):',
|
|
377
|
-
default: 'HEAD~1'
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
const projectPath = await input({
|
|
381
|
-
message: 'Project path:',
|
|
382
|
-
default: '.'
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
const exitCode = await diff(projectPath, baseRef, { explain: true });
|
|
386
|
-
process.exit(exitCode);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
if (action === 'init-hooks') {
|
|
390
|
-
const hookMode = await select({
|
|
391
|
-
message: 'Hook mode:',
|
|
392
|
-
choices: [
|
|
393
|
-
{ name: 'Scan all threats', value: 'scan' },
|
|
394
|
-
{ name: 'Diff only (block only NEW threats)', value: 'diff' }
|
|
395
|
-
]
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
const hookType = await select({
|
|
399
|
-
message: 'Hook system:',
|
|
400
|
-
choices: [
|
|
401
|
-
{ name: 'Auto-detect', value: 'auto' },
|
|
402
|
-
{ name: 'Husky', value: 'husky' },
|
|
403
|
-
{ name: 'pre-commit framework', value: 'pre-commit' },
|
|
404
|
-
{ name: 'Native git hooks', value: 'git' }
|
|
405
|
-
]
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
await initHooks('.', { type: hookType, mode: hookMode });
|
|
409
|
-
process.exit(0);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
const helpText = `
|
|
414
|
-
MUAD'DIB - npm & PyPI Supply Chain Threat Hunter
|
|
415
|
-
|
|
416
|
-
Usage:
|
|
417
|
-
muaddib Interactive mode
|
|
418
|
-
muaddib scan [path] [options] Scan a project
|
|
419
|
-
muaddib diff <ref> [path] Compare threats with a previous version
|
|
420
|
-
muaddib install <pkg> [options] Safe install (scan before install)
|
|
421
|
-
muaddib watch [path] Watch in real-time
|
|
422
|
-
muaddib sandbox <pkg> [options] Analyze in isolated Docker container
|
|
423
|
-
muaddib sandbox-report <pkg> Sandbox + detailed network report
|
|
424
|
-
muaddib evaluate [options] Run TPR/FPR/ADR evaluation suite
|
|
425
|
-
muaddib monitor [options] Start real-time npm/PyPI monitor
|
|
426
|
-
muaddib daemon [options] Start daemon
|
|
427
|
-
muaddib init-hooks [options] Setup git pre-commit hooks
|
|
428
|
-
muaddib remove-hooks [path] Remove MUAD'DIB git hooks
|
|
429
|
-
muaddib update Update IOCs
|
|
430
|
-
muaddib scrape Scrape new IOCs
|
|
431
|
-
muaddib feed [options] Threat feed (JSON)
|
|
432
|
-
muaddib serve [options] Threat feed HTTP server
|
|
433
|
-
muaddib detections [options] View monitor detections
|
|
434
|
-
muaddib stats [options] View scan statistics
|
|
435
|
-
muaddib replay [options] Replay ground-truth attacks
|
|
436
|
-
muaddib version Show version
|
|
437
|
-
|
|
438
|
-
Scan Options:
|
|
439
|
-
--json JSON output
|
|
440
|
-
--html [file] HTML report (default: muaddib-report.html)
|
|
441
|
-
--sarif [file] SARIF report (default: muaddib-results.sarif)
|
|
442
|
-
--explain Detailed explanations with MITRE references
|
|
443
|
-
--breakdown Show score breakdown by threat
|
|
444
|
-
--fail-on [level] Exit code threshold (critical|high|medium|low, default: high)
|
|
445
|
-
--webhook [url] Discord/Slack webhook (HTTPS only)
|
|
446
|
-
--paranoid Ultra-strict detection mode
|
|
447
|
-
--exclude [dir] Exclude directory from scan (repeatable)
|
|
448
|
-
--config [file] Custom config file (.muaddibrc.json format)
|
|
449
|
-
--entropy-threshold [n] Custom entropy threshold (0-8, default: 5.5)
|
|
450
|
-
--no-deobfuscate Disable deobfuscation pre-processing
|
|
451
|
-
--no-module-graph Disable cross-file dataflow analysis
|
|
452
|
-
--no-reachability Disable entry-point reachability analysis
|
|
453
|
-
--auto-sandbox Auto-trigger sandbox when static scan score >= 20 (requires Docker)
|
|
454
|
-
|
|
455
|
-
Temporal Options (scan):
|
|
456
|
-
--temporal Detect sudden lifecycle script changes
|
|
457
|
-
--temporal-ast Detect sudden dangerous API additions via AST diff
|
|
458
|
-
--temporal-publish Detect publish frequency anomalies
|
|
459
|
-
--temporal-maintainer Detect maintainer changes
|
|
460
|
-
--temporal-full All temporal analyses combined
|
|
461
|
-
|
|
462
|
-
Diff Examples:
|
|
463
|
-
muaddib diff HEAD~1 Compare with previous commit
|
|
464
|
-
muaddib diff v1.2.0 Compare with tag
|
|
465
|
-
muaddib diff main Compare with branch
|
|
466
|
-
muaddib diff abc1234 ./myproject Compare specific commit
|
|
467
|
-
|
|
468
|
-
Install Options:
|
|
469
|
-
--save-dev, -D Install as dev dependency
|
|
470
|
-
-g, --global Install globally
|
|
471
|
-
--force Force install despite threats
|
|
472
|
-
|
|
473
|
-
Sandbox Options:
|
|
474
|
-
--local Analyze a local path instead of npm package
|
|
475
|
-
--strict Block non-essential network access
|
|
476
|
-
--no-canary Disable honey token injection
|
|
477
|
-
|
|
478
|
-
Init-hooks Options:
|
|
479
|
-
--type [auto|husky|pre-commit|git] Hook system (default: auto)
|
|
480
|
-
--mode [scan|diff] scan=all threats, diff=new only
|
|
481
|
-
|
|
482
|
-
Evaluate Options:
|
|
483
|
-
--json JSON output
|
|
484
|
-
--benign-limit [n] Limit benign packages to scan
|
|
485
|
-
--refresh-benign Re-download benign packages
|
|
486
|
-
|
|
487
|
-
Feed/Serve Options:
|
|
488
|
-
--limit [n] Limit feed entries (default: 50)
|
|
489
|
-
--severity [level] Filter by severity (CRITICAL|HIGH|MEDIUM|LOW)
|
|
490
|
-
--since [date] Filter detections after date (ISO 8601)
|
|
491
|
-
--port [n] HTTP server port (default: 3000)
|
|
492
|
-
|
|
493
|
-
Monitor Options:
|
|
494
|
-
--verbose Show detailed output
|
|
495
|
-
--temporal --test <pkg> Test temporal analysis on a single package
|
|
496
|
-
--temporal-ast --test <pkg> Test AST diff on a single package
|
|
497
|
-
|
|
498
|
-
Detections Options:
|
|
499
|
-
--json JSON output
|
|
500
|
-
--stats Show aggregated detection statistics
|
|
501
|
-
|
|
502
|
-
Stats Options:
|
|
503
|
-
--json JSON output
|
|
504
|
-
--daily Show daily breakdown (last 7 days)
|
|
505
|
-
|
|
506
|
-
Replay Options:
|
|
507
|
-
--verbose Show detailed findings per attack
|
|
508
|
-
--json Machine-readable JSON output
|
|
509
|
-
GT-NNN Replay single attack by ID
|
|
510
|
-
`;
|
|
511
|
-
|
|
512
|
-
// Per-command help texts for subcommand --help
|
|
513
|
-
const commandHelp = {
|
|
514
|
-
scan: `
|
|
515
|
-
Usage: muaddib scan [path] [options]
|
|
516
|
-
|
|
517
|
-
Scan a project for supply-chain threats.
|
|
518
|
-
|
|
519
|
-
Arguments:
|
|
520
|
-
path Target directory to scan (default: .)
|
|
521
|
-
|
|
522
|
-
Options:
|
|
523
|
-
--json JSON output
|
|
524
|
-
--html [file] HTML report (default: muaddib-report.html)
|
|
525
|
-
--sarif [file] SARIF report (default: muaddib-results.sarif)
|
|
526
|
-
--explain Detailed explanations with MITRE references
|
|
527
|
-
--breakdown Show score breakdown by threat
|
|
528
|
-
--fail-on [level] Exit code threshold (critical|high|medium|low, default: high)
|
|
529
|
-
--webhook [url] Discord/Slack webhook (HTTPS only)
|
|
530
|
-
--paranoid Ultra-strict detection mode
|
|
531
|
-
--exclude [dir] Exclude directory from scan (repeatable)
|
|
532
|
-
--config [file] Custom config file (.muaddibrc.json format)
|
|
533
|
-
--entropy-threshold [n] Custom entropy threshold (0-8, default: 5.5)
|
|
534
|
-
--no-deobfuscate Disable deobfuscation pre-processing
|
|
535
|
-
--no-module-graph Disable cross-file dataflow analysis
|
|
536
|
-
--no-reachability Disable entry-point reachability analysis
|
|
537
|
-
--auto-sandbox Auto-trigger sandbox when static scan score >= 20 (requires Docker)
|
|
538
|
-
--temporal Detect sudden lifecycle script changes
|
|
539
|
-
--temporal-ast Detect sudden dangerous API additions
|
|
540
|
-
--temporal-publish Detect publish frequency anomalies
|
|
541
|
-
--temporal-maintainer Detect maintainer changes
|
|
542
|
-
--temporal-full All temporal analyses combined
|
|
543
|
-
|
|
544
|
-
Examples:
|
|
545
|
-
muaddib scan .
|
|
546
|
-
muaddib scan ./my-project --explain --paranoid
|
|
547
|
-
muaddib scan . --json > results.json
|
|
548
|
-
muaddib scan . --html report.html --explain
|
|
549
|
-
`,
|
|
550
|
-
diff: `
|
|
551
|
-
Usage: muaddib diff <ref> [path] [options]
|
|
552
|
-
|
|
553
|
-
Compare threats between two versions of a project.
|
|
554
|
-
Without <ref>, shows available tags and recent commits.
|
|
555
|
-
|
|
556
|
-
Arguments:
|
|
557
|
-
ref Commit hash, tag, or branch to compare with
|
|
558
|
-
path Target directory (default: .)
|
|
559
|
-
|
|
560
|
-
Options:
|
|
561
|
-
--json JSON output
|
|
562
|
-
--explain Detailed explanations
|
|
563
|
-
--fail-on [level] Exit code threshold (critical|high|medium|low)
|
|
564
|
-
--paranoid Ultra-strict detection mode
|
|
565
|
-
|
|
566
|
-
Examples:
|
|
567
|
-
muaddib diff HEAD~1
|
|
568
|
-
muaddib diff v1.2.0
|
|
569
|
-
muaddib diff main ./myproject
|
|
570
|
-
`,
|
|
571
|
-
install: `
|
|
572
|
-
Usage: muaddib install <package> [<package>...] [options]
|
|
573
|
-
|
|
574
|
-
Scan packages for threats before installing them.
|
|
575
|
-
|
|
576
|
-
Options:
|
|
577
|
-
--save-dev, -D Install as dev dependency
|
|
578
|
-
-g, --global Install globally
|
|
579
|
-
--force Force install despite detected threats
|
|
580
|
-
|
|
581
|
-
Examples:
|
|
582
|
-
muaddib install lodash
|
|
583
|
-
muaddib install express morgan --save-dev
|
|
584
|
-
muaddib install -g typescript
|
|
585
|
-
`,
|
|
586
|
-
sandbox: `
|
|
587
|
-
Usage: muaddib sandbox <package-name|path> [options]
|
|
588
|
-
|
|
589
|
-
Run dynamic analysis in an isolated Docker container.
|
|
590
|
-
Requires Docker to be installed and running.
|
|
591
|
-
|
|
592
|
-
Options:
|
|
593
|
-
--local Analyze a local path instead of npm package
|
|
594
|
-
--strict Block non-essential network access
|
|
595
|
-
--no-canary Disable honey token injection
|
|
596
|
-
|
|
597
|
-
Examples:
|
|
598
|
-
muaddib sandbox suspicious-pkg
|
|
599
|
-
muaddib sandbox ./local-pkg --local --strict
|
|
600
|
-
`,
|
|
601
|
-
'sandbox-report': `
|
|
602
|
-
Usage: muaddib sandbox-report <package-name|path> [options]
|
|
603
|
-
|
|
604
|
-
Run sandbox analysis with detailed network traffic report.
|
|
605
|
-
Same options as 'muaddib sandbox'.
|
|
606
|
-
`,
|
|
607
|
-
evaluate: `
|
|
608
|
-
Usage: muaddib evaluate [options]
|
|
609
|
-
|
|
610
|
-
Run the full TPR/FPR/ADR evaluation suite against ground truth,
|
|
611
|
-
benign packages, and adversarial samples.
|
|
612
|
-
|
|
613
|
-
Options:
|
|
614
|
-
--json JSON output
|
|
615
|
-
--benign-limit [n] Limit benign packages to scan
|
|
616
|
-
--refresh-benign Re-download benign packages
|
|
617
|
-
|
|
618
|
-
Examples:
|
|
619
|
-
muaddib evaluate
|
|
620
|
-
muaddib evaluate --json > eval-results.json
|
|
621
|
-
`,
|
|
622
|
-
monitor: `
|
|
623
|
-
Usage: muaddib monitor [options]
|
|
624
|
-
|
|
625
|
-
Start real-time monitoring of npm/PyPI registries for
|
|
626
|
-
newly published malicious packages.
|
|
627
|
-
|
|
628
|
-
Options:
|
|
629
|
-
--verbose Show detailed output
|
|
630
|
-
--temporal --test <pkg> Test temporal analysis on a single package
|
|
631
|
-
--temporal-ast --test <pkg> Test AST diff on a single package
|
|
632
|
-
|
|
633
|
-
Examples:
|
|
634
|
-
muaddib monitor
|
|
635
|
-
muaddib monitor --verbose
|
|
636
|
-
muaddib monitor --temporal --test lodash
|
|
637
|
-
`,
|
|
638
|
-
feed: `
|
|
639
|
-
Usage: muaddib feed [options]
|
|
640
|
-
|
|
641
|
-
Output the threat detection feed as JSON.
|
|
642
|
-
|
|
643
|
-
Options:
|
|
644
|
-
--limit [n] Limit entries (default: 50)
|
|
645
|
-
--severity [level] Filter by severity (CRITICAL|HIGH|MEDIUM|LOW)
|
|
646
|
-
--since [date] Filter after date (ISO 8601)
|
|
647
|
-
|
|
648
|
-
Examples:
|
|
649
|
-
muaddib feed
|
|
650
|
-
muaddib feed --severity CRITICAL --limit 10
|
|
651
|
-
`,
|
|
652
|
-
serve: `
|
|
653
|
-
Usage: muaddib serve [options]
|
|
654
|
-
|
|
655
|
-
Start an HTTP server serving the threat feed.
|
|
656
|
-
|
|
657
|
-
Options:
|
|
658
|
-
--port [n] Server port (default: 3000)
|
|
659
|
-
|
|
660
|
-
Examples:
|
|
661
|
-
muaddib serve
|
|
662
|
-
muaddib serve --port 8080
|
|
663
|
-
`,
|
|
664
|
-
detections: `
|
|
665
|
-
Usage: muaddib detections [options]
|
|
666
|
-
|
|
667
|
-
View detections recorded by the monitor.
|
|
668
|
-
|
|
669
|
-
Options:
|
|
670
|
-
--json Full JSON output
|
|
671
|
-
--stats Show aggregated detection statistics
|
|
672
|
-
|
|
673
|
-
Examples:
|
|
674
|
-
muaddib detections
|
|
675
|
-
muaddib detections --stats
|
|
676
|
-
muaddib detections --json > detections.json
|
|
677
|
-
`,
|
|
678
|
-
stats: `
|
|
679
|
-
Usage: muaddib stats [options]
|
|
680
|
-
|
|
681
|
-
View scan statistics from the monitor.
|
|
682
|
-
|
|
683
|
-
Options:
|
|
684
|
-
--json JSON output
|
|
685
|
-
--daily Show daily breakdown (last 7 days)
|
|
686
|
-
|
|
687
|
-
Examples:
|
|
688
|
-
muaddib stats
|
|
689
|
-
muaddib stats --daily
|
|
690
|
-
`,
|
|
691
|
-
replay: `
|
|
692
|
-
Usage: muaddib replay [options] [GT-NNN]
|
|
693
|
-
|
|
694
|
-
Replay ground-truth attack samples to verify detection.
|
|
695
|
-
|
|
696
|
-
Options:
|
|
697
|
-
--verbose, -v Show detailed findings per attack
|
|
698
|
-
--json Machine-readable JSON output
|
|
699
|
-
GT-NNN Replay a single attack by ID
|
|
700
|
-
|
|
701
|
-
Examples:
|
|
702
|
-
muaddib replay
|
|
703
|
-
muaddib replay --verbose
|
|
704
|
-
muaddib replay GT-001
|
|
705
|
-
`,
|
|
706
|
-
'init-hooks': `
|
|
707
|
-
Usage: muaddib init-hooks [options]
|
|
708
|
-
|
|
709
|
-
Setup git pre-commit hooks for automatic scanning.
|
|
710
|
-
|
|
711
|
-
Options:
|
|
712
|
-
--type [auto|husky|pre-commit|git] Hook system (default: auto)
|
|
713
|
-
--mode [scan|diff] scan=all threats, diff=new only
|
|
714
|
-
|
|
715
|
-
Examples:
|
|
716
|
-
muaddib init-hooks
|
|
717
|
-
muaddib init-hooks --type husky --mode diff
|
|
718
|
-
`,
|
|
719
|
-
'remove-hooks': `
|
|
720
|
-
Usage: muaddib remove-hooks [path]
|
|
721
|
-
|
|
722
|
-
Remove MUAD'DIB git hooks from a project.
|
|
723
|
-
`,
|
|
724
|
-
watch: `
|
|
725
|
-
Usage: muaddib watch [path]
|
|
726
|
-
|
|
727
|
-
Watch a project directory and re-scan on file changes.
|
|
728
|
-
|
|
729
|
-
Examples:
|
|
730
|
-
muaddib watch
|
|
731
|
-
muaddib watch ./my-project
|
|
732
|
-
`,
|
|
733
|
-
daemon: `
|
|
734
|
-
Usage: muaddib daemon [options]
|
|
735
|
-
|
|
736
|
-
Start the MUAD'DIB daemon for background monitoring.
|
|
737
|
-
|
|
738
|
-
Options:
|
|
739
|
-
--webhook [url] Discord/Slack webhook URL
|
|
740
|
-
|
|
741
|
-
Examples:
|
|
742
|
-
muaddib daemon
|
|
743
|
-
muaddib daemon --webhook https://discord.com/api/webhooks/...
|
|
744
|
-
`,
|
|
745
|
-
report: `
|
|
746
|
-
Usage: muaddib report --now | --status
|
|
747
|
-
|
|
748
|
-
Send or check status of daily monitor reports.
|
|
749
|
-
|
|
750
|
-
Options:
|
|
751
|
-
--now Send report immediately
|
|
752
|
-
--status Show report status
|
|
753
|
-
`,
|
|
754
|
-
};
|
|
755
|
-
|
|
756
|
-
// Show per-command help or global help
|
|
757
|
-
function showHelp(cmd) {
|
|
758
|
-
if (cmd && commandHelp[cmd]) {
|
|
759
|
-
console.log(commandHelp[cmd]);
|
|
760
|
-
} else {
|
|
761
|
-
console.log(helpText);
|
|
762
|
-
}
|
|
763
|
-
process.exit(0);
|
|
764
|
-
}
|
|
765
226
|
|
|
766
227
|
// Main
|
|
767
228
|
if (command === 'version' || command === '--version' || command === '-v') {
|