muaddib-scanner 2.2.8 → 2.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.fr.md +50 -13
- package/README.md +50 -13
- package/package.json +1 -1
- package/src/index.js +13 -3
- package/src/scanner/ast.js +12 -1
- package/src/scanner/obfuscation.js +7 -2
package/README.fr.md
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
Les attaques supply-chain npm et PyPI explosent. Shai-Hulud a compromis 25K+ repos en 2025. Les outils existants détectent, mais n'aident pas à répondre.
|
|
32
32
|
|
|
33
|
-
MUAD'DIB combine analyse statique + analyse dynamique (sandbox Docker) + **détection comportementale d'anomalies** (v2.0) + **validation ground truth** (v2.1) pour détecter les menaces ET guider votre réponse — même avant leur apparition dans une base d'IOC.
|
|
33
|
+
MUAD'DIB combine analyse statique + **moteur de désobfuscation** (v2.2.5) + **dataflow inter-module** (v2.2.6) + analyse dynamique (sandbox Docker) + **détection comportementale d'anomalies** (v2.0) + **validation ground truth** (v2.1) pour détecter les menaces ET guider votre réponse — même avant leur apparition dans une base d'IOC.
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
@@ -431,6 +431,10 @@ Détecte les patterns malveillants dans les fichiers YAML `.github/workflows/`,
|
|
|
431
431
|
| Hooking prototype (fetch, XMLHttpRequest) | T1557 | AST |
|
|
432
432
|
| Injection workflow (.github/workflows) | T1195.002 | AST |
|
|
433
433
|
| Harvest crypto wallets | T1005 | Dataflow |
|
|
434
|
+
| Require cache poisoning | T1574.001 | AST |
|
|
435
|
+
| Staged eval decode (eval+atob/Buffer) | T1140 | AST |
|
|
436
|
+
| Désobfuscation (string concat, charcode, base64, hex) | T1140 | Pré-traitement AST |
|
|
437
|
+
| Dataflow cross-fichiers (exfiltration inter-module) | T1041 | Module graph |
|
|
434
438
|
|
|
435
439
|
---
|
|
436
440
|
|
|
@@ -642,7 +646,7 @@ Les alertes apparaissent dans Security > Code scanning alerts.
|
|
|
642
646
|
## Architecture
|
|
643
647
|
|
|
644
648
|
```
|
|
645
|
-
MUAD'DIB 2.2 Scanner
|
|
649
|
+
MUAD'DIB 2.2.9 Scanner
|
|
646
650
|
|
|
|
647
651
|
+-- IOC Match (225 000+ packages, JSON DB)
|
|
648
652
|
| +-- OSV.dev npm dump (200K+ entrées MAL-*)
|
|
@@ -654,7 +658,17 @@ MUAD'DIB 2.2 Scanner
|
|
|
654
658
|
| +-- Snyk Known Malware
|
|
655
659
|
| +-- Static IOCs (Socket, Phylum)
|
|
656
660
|
|
|
|
657
|
-
+--
|
|
661
|
+
+-- Pré-traitement Désobfuscation (v2.2.5, --no-deobfuscate pour désactiver)
|
|
662
|
+
| +-- String concat folding, reconstruction CharCode
|
|
663
|
+
| +-- Décodage Base64, résolution Hex array
|
|
664
|
+
| +-- Propagation de constantes (Phase 2)
|
|
665
|
+
|
|
|
666
|
+
+-- Dataflow Inter-module (v2.2.6, --no-module-graph pour désactiver)
|
|
667
|
+
| +-- Graphe de dépendances, annotation exports teintés
|
|
668
|
+
| +-- Chaînes re-export 3 hops, analyse méthodes de classe
|
|
669
|
+
| +-- Détection credential read → network sink cross-fichiers
|
|
670
|
+
|
|
|
671
|
+
+-- 14 Scanners Parallèles (~95 règles)
|
|
658
672
|
| +-- AST Parse (acorn) — eval/Function, credential CLI theft, binary droppers, prototype hooks
|
|
659
673
|
| +-- Pattern Matching (shell, scripts)
|
|
660
674
|
| +-- Typosquat Detection (npm + PyPI, Levenshtein)
|
|
@@ -678,6 +692,12 @@ MUAD'DIB 2.2 Scanner
|
|
|
678
692
|
| +-- Décomposition Score (scoring explicable par règle)
|
|
679
693
|
| +-- API Threat Feed (serveur HTTP, flux JSON pour SIEM)
|
|
680
694
|
|
|
|
695
|
+
+-- Réduction FP Post-traitement (v2.2.8-v2.2.9)
|
|
696
|
+
| +-- Downgrade sévérité par comptage (dynamic_require, dataflow, etc.)
|
|
697
|
+
| +-- Cap scoring prototype_hook MEDIUM
|
|
698
|
+
| +-- Obfuscation dans dist/build → LOW
|
|
699
|
+
| +-- Filtrage env vars safe + préfixes
|
|
700
|
+
|
|
|
681
701
|
+-- Paranoid Mode (ultra-strict)
|
|
682
702
|
+-- Docker Sandbox (analyse comportementale, capture réseau, canary tokens, CI-aware)
|
|
683
703
|
+-- Moniteur Zero-Day (interne : polling RSS npm + PyPI, alertes Discord, rapport quotidien)
|
|
@@ -696,14 +716,31 @@ Output (CLI, JSON, HTML, SARIF, Webhook, Threat Feed)
|
|
|
696
716
|
|
|
697
717
|
## Metriques d'evaluation
|
|
698
718
|
|
|
699
|
-
|
|
|
700
|
-
|
|
701
|
-
|
|
|
719
|
+
| Metrique | Resultat | Details |
|
|
720
|
+
|----------|----------|---------|
|
|
721
|
+
| **TPR** (Ground Truth) | **100%** (4/4) | Attaques reelles : event-stream, ua-parser-js, coa, node-ipc |
|
|
722
|
+
| **FPR** (Benign) | **17.5%** (92/527) | 529 packages npm, vrai code source via `npm pack`, seuil > 20 |
|
|
723
|
+
| **ADR** (Adversarial) | **100%** (35/35) | 35 samples evasifs sur 4 vagues red team |
|
|
724
|
+
| **Holdouts** (pre-tuning) | 40/40 pass | Tous les holdouts passent apres corrections |
|
|
725
|
+
|
|
726
|
+
**Progression FPR** : 0% (invalide, dirs vides, v2.2.0-v2.2.6) → 38% (premiere vraie mesure, v2.2.7) → 19.4% (v2.2.8) → **17.5%** (v2.2.9)
|
|
727
|
+
|
|
728
|
+
**Progression holdout** (scores pre-tuning, regles gelees) :
|
|
729
|
+
|
|
730
|
+
| Holdout | Score | Focus |
|
|
731
|
+
|---------|-------|-------|
|
|
732
|
+
| v1 | 30% (3/10) | Patterns generaux |
|
|
733
|
+
| v2 | 40% (4/10) | Env charcode, lifecycle, prototype |
|
|
734
|
+
| v3 | 60% (6/10) | Require cache, DNS TXT, reverse shell |
|
|
735
|
+
| v4 | **80%** (8/10) | Efficacite desobfuscation |
|
|
736
|
+
| v5 | 50% (5/10) | Dataflow inter-module (nouveau scanner) |
|
|
737
|
+
|
|
738
|
+
- **TPR** (True Positive Rate) : taux de detection sur 4 attaques supply-chain reelles (event-stream, ua-parser-js, coa, node-ipc)
|
|
739
|
+
- **FPR** (False Positive Rate) : packages avec score > 20 sur 529 packages npm reels (code source scanne, pas des dirs vides)
|
|
740
|
+
- **ADR** (Adversarial Detection Rate) : taux de detection sur 35 samples malveillants evasifs sur 4 vagues red team
|
|
741
|
+
- **Holdout** (pre-tuning) : taux de detection sur 10 samples jamais vus avec regles gelees (mesure de generalisation)
|
|
702
742
|
|
|
703
|
-
|
|
704
|
-
- **FPR** (False Positive Rate) : packages avec score > 20 sur 98 packages npm populaires
|
|
705
|
-
- **ADR** (Adversarial Detection Rate) : taux de detection sur 35 samples malveillants evasifs (4 vagues red team + holdout promu)
|
|
706
|
-
- **Holdout** (pre-tuning) : taux de detection sur 10 samples jamais vus avant correction des regles (mesure de generalisation)
|
|
743
|
+
Datasets : 529 npm + 132 PyPI packages benins, 35 samples adversariaux, 50 samples holdout (5 batches), 65 packages malveillants documentes.
|
|
707
744
|
|
|
708
745
|
Voir [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md) pour le protocole experimental complet.
|
|
709
746
|
|
|
@@ -739,13 +776,13 @@ npm test
|
|
|
739
776
|
|
|
740
777
|
### Tests
|
|
741
778
|
|
|
742
|
-
- **
|
|
779
|
+
- **822 tests unitaires/intégration** sur 20 fichiers modulaires - 74% coverage via [Codecov](https://codecov.io/gh/DNSZLSK/muad-dib)
|
|
743
780
|
- **56 tests de fuzzing** - YAML malformé, JSON invalide, fichiers binaires, ReDoS, unicode, inputs 10MB
|
|
744
781
|
- **35 samples adversariaux** - Packages malveillants évasifs, taux de détection 35/35 (100% ADR)
|
|
782
|
+
- **50 samples holdout** - 5 batches de 10, scores pre-tuning : 30% → 40% → 60% → 80% → 50%
|
|
745
783
|
- **8 tests multi-facteur typosquat** - Cas limites et comportement cache
|
|
746
784
|
- **Validation ground truth** - 5/5 attaques réelles détectées (event-stream, ua-parser-js, coa, node-ipc, colors)
|
|
747
|
-
- **Validation faux positifs** -
|
|
748
|
-
- **Validation holdout** - 3/10 détection sur samples jamais vus avant correction (30% pre-tuning)
|
|
785
|
+
- **Validation faux positifs** - 17.5% FPR (92/527) sur vrai code source npm via `npm pack` (mesure honnête)
|
|
749
786
|
- **Audit ESLint sécurité** - `eslint-plugin-security` avec 14 règles activées
|
|
750
787
|
|
|
751
788
|
---
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
npm and PyPI supply-chain attacks are exploding. Shai-Hulud compromised 25K+ repos in 2025. Existing tools detect threats but don't help you respond.
|
|
32
32
|
|
|
33
|
-
MUAD'DIB combines static analysis + 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.
|
|
33
|
+
MUAD'DIB combines static analysis + **deobfuscation engine** (v2.2.5) + **inter-module dataflow** (v2.2.6) + 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
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
@@ -432,6 +432,10 @@ Detects malicious patterns in `.github/workflows/` YAML files, including Shai-Hu
|
|
|
432
432
|
| Prototype hooking (fetch, XMLHttpRequest) | T1557 | AST |
|
|
433
433
|
| Workflow injection (.github/workflows) | T1195.002 | AST |
|
|
434
434
|
| Crypto wallet harvesting | T1005 | Dataflow |
|
|
435
|
+
| Require cache poisoning | T1574.001 | AST |
|
|
436
|
+
| Staged eval decode (eval+atob/Buffer) | T1140 | AST |
|
|
437
|
+
| Deobfuscation (string concat, charcode, base64, hex) | T1140 | AST pre-processing |
|
|
438
|
+
| Cross-file dataflow (inter-module exfiltration) | T1041 | Module graph |
|
|
435
439
|
|
|
436
440
|
---
|
|
437
441
|
|
|
@@ -643,7 +647,7 @@ Alerts appear in Security > Code scanning alerts.
|
|
|
643
647
|
## Architecture
|
|
644
648
|
|
|
645
649
|
```
|
|
646
|
-
MUAD'DIB 2.2 Scanner
|
|
650
|
+
MUAD'DIB 2.2.9 Scanner
|
|
647
651
|
|
|
|
648
652
|
+-- IOC Match (225,000+ packages, JSON DB)
|
|
649
653
|
| +-- OSV.dev npm dump (200K+ MAL-* entries)
|
|
@@ -655,7 +659,17 @@ MUAD'DIB 2.2 Scanner
|
|
|
655
659
|
| +-- Snyk Known Malware
|
|
656
660
|
| +-- Static IOCs (Socket, Phylum)
|
|
657
661
|
|
|
|
658
|
-
+--
|
|
662
|
+
+-- Deobfuscation Pre-processing (v2.2.5, --no-deobfuscate to disable)
|
|
663
|
+
| +-- String concat folding, CharCode reconstruction
|
|
664
|
+
| +-- Base64 decode, Hex array resolution
|
|
665
|
+
| +-- Const propagation (Phase 2)
|
|
666
|
+
|
|
|
667
|
+
+-- Inter-module Dataflow (v2.2.6, --no-module-graph to disable)
|
|
668
|
+
| +-- Module dependency graph, tainted export annotation
|
|
669
|
+
| +-- 3-hop re-export chains, class method analysis
|
|
670
|
+
| +-- Cross-file credential read -> network sink detection
|
|
671
|
+
|
|
|
672
|
+
+-- 14 Parallel Scanners (~95 rules)
|
|
659
673
|
| +-- AST Parse (acorn) — eval/Function, credential CLI theft, binary droppers, prototype hooks
|
|
660
674
|
| +-- Pattern Matching (shell, scripts)
|
|
661
675
|
| +-- Obfuscation Detection (skip .min.js, ignore hex/unicode alone)
|
|
@@ -681,6 +695,12 @@ MUAD'DIB 2.2 Scanner
|
|
|
681
695
|
| +-- Score Breakdown (explainable per-rule scoring)
|
|
682
696
|
| +-- Threat Feed API (HTTP server, JSON feed for SIEM)
|
|
683
697
|
|
|
|
698
|
+
+-- FP Reduction Post-processing (v2.2.8-v2.2.9)
|
|
699
|
+
| +-- Count-based severity downgrade (dynamic_require, dataflow, etc.)
|
|
700
|
+
| +-- Framework prototype scoring cap
|
|
701
|
+
| +-- Obfuscation in dist/build → LOW
|
|
702
|
+
| +-- Safe env var + prefix filtering
|
|
703
|
+
|
|
|
684
704
|
+-- Paranoid Mode (ultra-strict)
|
|
685
705
|
+-- Docker Sandbox (behavioral analysis, network capture, canary tokens, CI-aware)
|
|
686
706
|
+-- Zero-Day Monitor (internal: npm + PyPI RSS polling, Discord alerts, daily report)
|
|
@@ -699,14 +719,31 @@ Output (CLI, JSON, HTML, SARIF, Webhook, Threat Feed)
|
|
|
699
719
|
|
|
700
720
|
## Evaluation Metrics
|
|
701
721
|
|
|
702
|
-
|
|
|
703
|
-
|
|
704
|
-
|
|
|
722
|
+
| Metric | Result | Details |
|
|
723
|
+
|--------|--------|---------|
|
|
724
|
+
| **TPR** (Ground Truth) | **100%** (4/4) | Real-world attacks: event-stream, ua-parser-js, coa, node-ipc |
|
|
725
|
+
| **FPR** (Benign) | **17.5%** (92/527) | 529 npm packages, real source code via `npm pack`, threshold > 20 |
|
|
726
|
+
| **ADR** (Adversarial) | **100%** (35/35) | 35 evasive samples across 4 red-team waves |
|
|
727
|
+
| **Holdouts** (pre-tuning) | 40/40 pass | All holdout samples pass after corrections |
|
|
728
|
+
|
|
729
|
+
**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)
|
|
730
|
+
|
|
731
|
+
**Holdout progression** (pre-tuning scores, rules frozen):
|
|
732
|
+
|
|
733
|
+
| Holdout | Score | Focus |
|
|
734
|
+
|---------|-------|-------|
|
|
735
|
+
| v1 | 30% (3/10) | General patterns |
|
|
736
|
+
| v2 | 40% (4/10) | Env charcode, lifecycle, prototype |
|
|
737
|
+
| v3 | 60% (6/10) | Require cache, DNS TXT, reverse shell |
|
|
738
|
+
| v4 | **80%** (8/10) | Deobfuscation effectiveness |
|
|
739
|
+
| v5 | 50% (5/10) | Inter-module dataflow (new scanner) |
|
|
740
|
+
|
|
741
|
+
- **TPR** (True Positive Rate): detection rate on 4 real-world supply-chain attacks (event-stream, ua-parser-js, coa, node-ipc)
|
|
742
|
+
- **FPR** (False Positive Rate): packages scoring > 20 out of 529 real npm packages (source code scanned, not empty dirs)
|
|
743
|
+
- **ADR** (Adversarial Detection Rate): detection rate on 35 evasive malicious samples across 4 red-team waves
|
|
744
|
+
- **Holdout** (pre-tuning): detection rate on 10 unseen samples with rules frozen (measures generalization)
|
|
705
745
|
|
|
706
|
-
|
|
707
|
-
- **FPR** (False Positive Rate): packages scoring > 20 out of 98 popular npm packages
|
|
708
|
-
- **ADR** (Adversarial Detection Rate): detection rate on 35 evasive malicious samples across 4 red-team waves + promoted holdout
|
|
709
|
-
- **Holdout** (pre-tuning): detection rate on 10 unseen samples before any rule correction (measures generalization)
|
|
746
|
+
Datasets: 529 npm + 132 PyPI benign packages, 35 adversarial samples, 50 holdout samples (5 batches), 65 documented malware packages.
|
|
710
747
|
|
|
711
748
|
See [Evaluation Methodology](docs/EVALUATION_METHODOLOGY.md) for the full experimental protocol.
|
|
712
749
|
|
|
@@ -742,13 +779,13 @@ npm test
|
|
|
742
779
|
|
|
743
780
|
### Testing
|
|
744
781
|
|
|
745
|
-
- **
|
|
782
|
+
- **822 unit/integration tests** across 20 modular test files - 74% code coverage via [Codecov](https://codecov.io/gh/DNSZLSK/muad-dib)
|
|
746
783
|
- **56 fuzz tests** - Malformed YAML, invalid JSON, binary files, ReDoS, unicode, 10MB inputs
|
|
747
784
|
- **35 adversarial samples** - Evasive malicious packages, 35/35 detection rate (100% ADR)
|
|
785
|
+
- **50 holdout samples** - 5 batches of 10, pre-tuning scores: 30% → 40% → 60% → 80% → 50%
|
|
748
786
|
- **8 multi-factor typosquat tests** - Edge cases and cache behavior
|
|
749
787
|
- **Ground truth validation** - 5/5 real-world attacks detected (event-stream, ua-parser-js, coa, node-ipc, colors)
|
|
750
|
-
- **False positive validation** -
|
|
751
|
-
- **Holdout validation** - 3/10 detection on unseen samples before rule corrections (30% pre-tuning)
|
|
788
|
+
- **False positive validation** - 17.5% FPR (92/527) on real npm source code via `npm pack` (honest measurement)
|
|
752
789
|
- **ESLint security audit** - `eslint-plugin-security` with 14 rules enabled
|
|
753
790
|
|
|
754
791
|
---
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -73,7 +73,9 @@ const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
|
|
|
73
73
|
const FP_COUNT_THRESHOLDS = {
|
|
74
74
|
dynamic_require: { maxCount: 10, from: 'HIGH', to: 'LOW' },
|
|
75
75
|
dangerous_call_function: { maxCount: 5, from: 'MEDIUM', to: 'LOW' },
|
|
76
|
-
require_cache_poison: { maxCount: 3, from: 'CRITICAL', to: 'LOW' }
|
|
76
|
+
require_cache_poison: { maxCount: 3, from: 'CRITICAL', to: 'LOW' },
|
|
77
|
+
suspicious_dataflow: { maxCount: 5, to: 'LOW' },
|
|
78
|
+
obfuscation_detected: { maxCount: 3, to: 'LOW' }
|
|
77
79
|
};
|
|
78
80
|
|
|
79
81
|
// Custom class prototypes that HTTP frameworks legitimately extend.
|
|
@@ -94,7 +96,7 @@ function applyFPReductions(threats) {
|
|
|
94
96
|
// Count-based downgrade: if a threat type appears too many times,
|
|
95
97
|
// it's a framework/plugin system, not malware
|
|
96
98
|
const rule = FP_COUNT_THRESHOLDS[t.type];
|
|
97
|
-
if (rule && typeCounts[t.type] > rule.maxCount && t.severity === rule.from) {
|
|
99
|
+
if (rule && typeCounts[t.type] > rule.maxCount && (!rule.from || t.severity === rule.from)) {
|
|
98
100
|
t.severity = rule.to;
|
|
99
101
|
}
|
|
100
102
|
|
|
@@ -638,10 +640,18 @@ async function run(targetPath, options = {}) {
|
|
|
638
640
|
const mediumCount = deduped.filter(t => t.severity === 'MEDIUM').length;
|
|
639
641
|
const lowCount = deduped.filter(t => t.severity === 'LOW').length;
|
|
640
642
|
|
|
643
|
+
// Cap MEDIUM prototype_hook contribution to 15 points max (5 × MEDIUM=3)
|
|
644
|
+
// Frameworks like Restify have 50+ prototype extensions that are not malicious
|
|
645
|
+
const mediumProtoHookCount = deduped.filter(t => t.type === 'prototype_hook' && t.severity === 'MEDIUM').length;
|
|
646
|
+
const PROTO_HOOK_MEDIUM_CAP = 15;
|
|
647
|
+
const protoHookPoints = Math.min(mediumProtoHookCount * SEVERITY_WEIGHTS.MEDIUM, PROTO_HOOK_MEDIUM_CAP);
|
|
648
|
+
const otherMediumCount = mediumCount - mediumProtoHookCount;
|
|
649
|
+
|
|
641
650
|
let riskScore = 0;
|
|
642
651
|
riskScore += criticalCount * SEVERITY_WEIGHTS.CRITICAL;
|
|
643
652
|
riskScore += highCount * SEVERITY_WEIGHTS.HIGH;
|
|
644
|
-
riskScore +=
|
|
653
|
+
riskScore += otherMediumCount * SEVERITY_WEIGHTS.MEDIUM;
|
|
654
|
+
riskScore += protoHookPoints;
|
|
645
655
|
riskScore += lowCount * SEVERITY_WEIGHTS.LOW;
|
|
646
656
|
riskScore = Math.min(MAX_RISK_SCORE, riskScore);
|
|
647
657
|
|
package/src/scanner/ast.js
CHANGED
|
@@ -31,9 +31,15 @@ const SENSITIVE_STRINGS = [
|
|
|
31
31
|
// Env vars that are safe and should NOT be flagged (common config/runtime vars)
|
|
32
32
|
const SAFE_ENV_VARS = [
|
|
33
33
|
'NODE_ENV', 'PORT', 'HOST', 'HOSTNAME', 'PWD', 'HOME', 'PATH',
|
|
34
|
-
'LANG', 'TERM', 'CI', 'DEBUG', 'VERBOSE', 'LOG_LEVEL'
|
|
34
|
+
'LANG', 'TERM', 'CI', 'DEBUG', 'VERBOSE', 'LOG_LEVEL',
|
|
35
|
+
'SHELL', 'USER', 'LOGNAME', 'EDITOR', 'TZ',
|
|
36
|
+
'NODE_DEBUG', 'NODE_PATH', 'NODE_OPTIONS',
|
|
37
|
+
'DISPLAY', 'COLORTERM', 'FORCE_COLOR', 'NO_COLOR', 'TERM_PROGRAM'
|
|
35
38
|
];
|
|
36
39
|
|
|
40
|
+
// Env var prefixes that are safe (npm metadata, locale settings)
|
|
41
|
+
const SAFE_ENV_PREFIXES = ['npm_config_', 'npm_lifecycle_', 'npm_package_', 'lc_'];
|
|
42
|
+
|
|
37
43
|
// Env var keywords to detect sensitive environment access (separate from SENSITIVE_STRINGS)
|
|
38
44
|
const ENV_SENSITIVE_KEYWORDS = [
|
|
39
45
|
'TOKEN', 'SECRET', 'KEY', 'PASSWORD', 'CREDENTIAL', 'AUTH'
|
|
@@ -914,6 +920,11 @@ function analyzeFile(content, filePath, basePath) {
|
|
|
914
920
|
if (SAFE_ENV_VARS.includes(envVar)) {
|
|
915
921
|
return;
|
|
916
922
|
}
|
|
923
|
+
// Skip safe prefixes (npm_config_*, npm_lifecycle_*, npm_package_*, LC_*)
|
|
924
|
+
const envLower = envVar.toLowerCase();
|
|
925
|
+
if (SAFE_ENV_PREFIXES.some(p => envLower.startsWith(p))) {
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
917
928
|
// Flag only vars containing sensitive keywords
|
|
918
929
|
if (ENV_SENSITIVE_KEYWORDS.some(s => envVar.toUpperCase().includes(s))) {
|
|
919
930
|
threats.push({
|
|
@@ -29,7 +29,12 @@ function detectObfuscation(targetPath) {
|
|
|
29
29
|
|
|
30
30
|
const signals = [];
|
|
31
31
|
let score = 0;
|
|
32
|
-
const
|
|
32
|
+
const basename = path.basename(file);
|
|
33
|
+
const isMinified = basename.endsWith('.min.js');
|
|
34
|
+
const isBundled = basename.endsWith('.bundle.js');
|
|
35
|
+
const pathParts = relativePath.split(path.sep);
|
|
36
|
+
const isInDistOrBuild = pathParts.some(p => p === 'dist' || p === 'build');
|
|
37
|
+
const isPackageOutput = isMinified || isBundled || isInDistOrBuild;
|
|
33
38
|
|
|
34
39
|
// 1. Ratio code sur une seule ligne (skip .min.js — minification, not obfuscation)
|
|
35
40
|
if (!isMinified) {
|
|
@@ -86,7 +91,7 @@ function detectObfuscation(targetPath) {
|
|
|
86
91
|
if (score >= 40) {
|
|
87
92
|
threats.push({
|
|
88
93
|
type: 'obfuscation_detected',
|
|
89
|
-
severity: score >= 70 ? 'CRITICAL' : 'HIGH',
|
|
94
|
+
severity: isPackageOutput ? 'LOW' : (score >= 70 ? 'CRITICAL' : 'HIGH'),
|
|
90
95
|
message: `Code obfusque (score: ${score}). Signaux: ${signals.join(', ')}`,
|
|
91
96
|
file: relativePath
|
|
92
97
|
});
|