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