muaddib-scanner 2.5.6 → 2.5.8

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/iocs/builtin.yaml CHANGED
@@ -7,39 +7,108 @@ packages:
7
7
  version: "4.1.1"
8
8
  source: shai-hulud-v1
9
9
  - name: "ng2-file-upload"
10
- version: "*"
10
+ version: "7.0.2"
11
+ source: shai-hulud-v1
12
+ - name: "ng2-file-upload"
13
+ version: "7.0.3"
14
+ source: shai-hulud-v1
15
+ - name: "ng2-file-upload"
16
+ version: "8.0.1"
17
+ source: shai-hulud-v1
18
+ - name: "ng2-file-upload"
19
+ version: "8.0.2"
20
+ source: shai-hulud-v1
21
+ - name: "ng2-file-upload"
22
+ version: "8.0.3"
23
+ source: shai-hulud-v1
24
+ - name: "ng2-file-upload"
25
+ version: "9.0.1"
11
26
  source: shai-hulud-v1
12
27
  - name: "ngx-bootstrap"
13
- version: "*"
28
+ version: "18.1.4"
29
+ source: shai-hulud-v1
30
+ - name: "ngx-bootstrap"
31
+ version: "19.0.3"
32
+ source: shai-hulud-v1
33
+ - name: "ngx-bootstrap"
34
+ version: "19.0.4"
35
+ source: shai-hulud-v1
36
+ - name: "ngx-bootstrap"
37
+ version: "20.0.3"
38
+ source: shai-hulud-v1
39
+ - name: "ngx-bootstrap"
40
+ version: "20.0.4"
41
+ source: shai-hulud-v1
42
+ - name: "ngx-bootstrap"
43
+ version: "20.0.5"
44
+ source: shai-hulud-v1
45
+ - name: "ngx-bootstrap"
46
+ version: "20.0.6"
14
47
  source: shai-hulud-v1
15
48
 
16
49
  # Shai-Hulud v2 (novembre 2025)
17
50
  - name: "@asyncapi/specs"
18
- version: "*"
51
+ version: "6.8.2"
52
+ source: shai-hulud-v2
53
+ - name: "@asyncapi/specs"
54
+ version: "6.8.3"
55
+ source: shai-hulud-v2
56
+ - name: "@asyncapi/specs"
57
+ version: "6.9.1"
58
+ source: shai-hulud-v2
59
+ - name: "@asyncapi/specs"
60
+ version: "6.10.1"
19
61
  source: shai-hulud-v2
20
62
  - name: "@asyncapi/openapi-schema-parser"
21
- version: "*"
63
+ version: "3.0.25"
64
+ source: shai-hulud-v2
65
+ - name: "@asyncapi/openapi-schema-parser"
66
+ version: "3.0.26"
22
67
  source: shai-hulud-v2
23
68
  - name: "get-them-args"
24
- version: "*"
69
+ version: "1.3.3"
25
70
  source: shai-hulud-v2
26
71
  - name: "kill-port"
27
- version: "*"
72
+ version: "2.0.2"
73
+ source: shai-hulud-v2
74
+ - name: "kill-port"
75
+ version: "2.0.3"
28
76
  source: shai-hulud-v2
29
77
  - name: "shell-exec"
30
- version: "*"
78
+ version: "1.1.3"
79
+ source: shai-hulud-v2
80
+ - name: "shell-exec"
81
+ version: "1.1.4"
31
82
  source: shai-hulud-v2
32
83
  - name: "posthog-node"
33
- version: "*"
84
+ version: "4.18.1"
85
+ source: shai-hulud-v2
86
+ - name: "posthog-node"
87
+ version: "5.11.3"
88
+ source: shai-hulud-v2
89
+ - name: "posthog-node"
90
+ version: "5.13.3"
34
91
  source: shai-hulud-v2
35
92
  - name: "posthog-js"
36
- version: "*"
93
+ version: "1.297.3"
37
94
  source: shai-hulud-v2
38
95
  - name: "@postman/tunnel-agent"
39
- version: "*"
96
+ version: "0.6.5"
97
+ source: shai-hulud-v2
98
+ - name: "@postman/tunnel-agent"
99
+ version: "0.6.6"
100
+ source: shai-hulud-v2
101
+ - name: "@postman/tunnel-agent"
102
+ version: "0.6.7"
40
103
  source: shai-hulud-v2
41
104
  - name: "@zapier/secret-scrubber"
42
- version: "*"
105
+ version: "1.1.3"
106
+ source: shai-hulud-v2
107
+ - name: "@zapier/secret-scrubber"
108
+ version: "1.1.4"
109
+ source: shai-hulud-v2
110
+ - name: "@zapier/secret-scrubber"
111
+ version: "1.1.5"
43
112
  source: shai-hulud-v2
44
113
 
45
114
  # Shai-Hulud v3 Golden Path (28 decembre 2025)
@@ -21,9 +21,21 @@ packages:
21
21
  - https://www.wiz.io/blog/shai-hulud-npm-supply-chain-attack
22
22
  mitre: T1195.002
23
23
 
24
- - id: SHAI-HULUD-V1-002
24
+ - id: SHAI-HULUD-V1-002a
25
25
  name: "ng2-file-upload"
26
- version: "*"
26
+ version: "7.0.2"
27
+ severity: critical
28
+ confidence: high
29
+ source: shai-hulud-v1
30
+ introduced: "2025-09-01"
31
+ description: "Package compromis par Shai-Hulud v1"
32
+ references:
33
+ - https://blog.phylum.io/shai-hulud-npm-worm
34
+ mitre: T1195.002
35
+
36
+ - id: SHAI-HULUD-V1-002b
37
+ name: "ng2-file-upload"
38
+ version: "7.0.3"
27
39
  severity: critical
28
40
  confidence: high
29
41
  source: shai-hulud-v1
@@ -33,9 +45,129 @@ packages:
33
45
  - https://blog.phylum.io/shai-hulud-npm-worm
34
46
  mitre: T1195.002
35
47
 
36
- - id: SHAI-HULUD-V1-003
48
+ - id: SHAI-HULUD-V1-002c
49
+ name: "ng2-file-upload"
50
+ version: "8.0.1"
51
+ severity: critical
52
+ confidence: high
53
+ source: shai-hulud-v1
54
+ introduced: "2025-09-01"
55
+ description: "Package compromis par Shai-Hulud v1"
56
+ references:
57
+ - https://blog.phylum.io/shai-hulud-npm-worm
58
+ mitre: T1195.002
59
+
60
+ - id: SHAI-HULUD-V1-002d
61
+ name: "ng2-file-upload"
62
+ version: "8.0.2"
63
+ severity: critical
64
+ confidence: high
65
+ source: shai-hulud-v1
66
+ introduced: "2025-09-01"
67
+ description: "Package compromis par Shai-Hulud v1"
68
+ references:
69
+ - https://blog.phylum.io/shai-hulud-npm-worm
70
+ mitre: T1195.002
71
+
72
+ - id: SHAI-HULUD-V1-002e
73
+ name: "ng2-file-upload"
74
+ version: "8.0.3"
75
+ severity: critical
76
+ confidence: high
77
+ source: shai-hulud-v1
78
+ introduced: "2025-09-01"
79
+ description: "Package compromis par Shai-Hulud v1"
80
+ references:
81
+ - https://blog.phylum.io/shai-hulud-npm-worm
82
+ mitre: T1195.002
83
+
84
+ - id: SHAI-HULUD-V1-002f
85
+ name: "ng2-file-upload"
86
+ version: "9.0.1"
87
+ severity: critical
88
+ confidence: high
89
+ source: shai-hulud-v1
90
+ introduced: "2025-09-01"
91
+ description: "Package compromis par Shai-Hulud v1"
92
+ references:
93
+ - https://blog.phylum.io/shai-hulud-npm-worm
94
+ mitre: T1195.002
95
+
96
+ - id: SHAI-HULUD-V1-003a
37
97
  name: "ngx-bootstrap"
38
- version: "*"
98
+ version: "18.1.4"
99
+ severity: critical
100
+ confidence: high
101
+ source: shai-hulud-v1
102
+ introduced: "2025-09-01"
103
+ description: "Package compromis par Shai-Hulud v1"
104
+ references:
105
+ - https://blog.phylum.io/shai-hulud-npm-worm
106
+ mitre: T1195.002
107
+
108
+ - id: SHAI-HULUD-V1-003b
109
+ name: "ngx-bootstrap"
110
+ version: "19.0.3"
111
+ severity: critical
112
+ confidence: high
113
+ source: shai-hulud-v1
114
+ introduced: "2025-09-01"
115
+ description: "Package compromis par Shai-Hulud v1"
116
+ references:
117
+ - https://blog.phylum.io/shai-hulud-npm-worm
118
+ mitre: T1195.002
119
+
120
+ - id: SHAI-HULUD-V1-003c
121
+ name: "ngx-bootstrap"
122
+ version: "19.0.4"
123
+ severity: critical
124
+ confidence: high
125
+ source: shai-hulud-v1
126
+ introduced: "2025-09-01"
127
+ description: "Package compromis par Shai-Hulud v1"
128
+ references:
129
+ - https://blog.phylum.io/shai-hulud-npm-worm
130
+ mitre: T1195.002
131
+
132
+ - id: SHAI-HULUD-V1-003d
133
+ name: "ngx-bootstrap"
134
+ version: "20.0.3"
135
+ severity: critical
136
+ confidence: high
137
+ source: shai-hulud-v1
138
+ introduced: "2025-09-01"
139
+ description: "Package compromis par Shai-Hulud v1"
140
+ references:
141
+ - https://blog.phylum.io/shai-hulud-npm-worm
142
+ mitre: T1195.002
143
+
144
+ - id: SHAI-HULUD-V1-003e
145
+ name: "ngx-bootstrap"
146
+ version: "20.0.4"
147
+ severity: critical
148
+ confidence: high
149
+ source: shai-hulud-v1
150
+ introduced: "2025-09-01"
151
+ description: "Package compromis par Shai-Hulud v1"
152
+ references:
153
+ - https://blog.phylum.io/shai-hulud-npm-worm
154
+ mitre: T1195.002
155
+
156
+ - id: SHAI-HULUD-V1-003f
157
+ name: "ngx-bootstrap"
158
+ version: "20.0.5"
159
+ severity: critical
160
+ confidence: high
161
+ source: shai-hulud-v1
162
+ introduced: "2025-09-01"
163
+ description: "Package compromis par Shai-Hulud v1"
164
+ references:
165
+ - https://blog.phylum.io/shai-hulud-npm-worm
166
+ mitre: T1195.002
167
+
168
+ - id: SHAI-HULUD-V1-003g
169
+ name: "ngx-bootstrap"
170
+ version: "20.0.6"
39
171
  severity: critical
40
172
  confidence: high
41
173
  source: shai-hulud-v1
@@ -48,9 +180,45 @@ packages:
48
180
  # ============================================
49
181
  # SHAI-HULUD v2 "The Second Coming" (Novembre 2025)
50
182
  # ============================================
51
- - id: SHAI-HULUD-V2-001
183
+ - id: SHAI-HULUD-V2-001a
52
184
  name: "@asyncapi/specs"
53
- version: "*"
185
+ version: "6.8.2"
186
+ severity: critical
187
+ confidence: high
188
+ source: shai-hulud-v2
189
+ introduced: "2025-11-01"
190
+ description: "Package compromis par Shai-Hulud v2 - inclut dead man's switch"
191
+ references:
192
+ - https://www.wiz.io/blog/shai-hulud-npm-supply-chain-attack
193
+ mitre: T1195.002
194
+
195
+ - id: SHAI-HULUD-V2-001b
196
+ name: "@asyncapi/specs"
197
+ version: "6.8.3"
198
+ severity: critical
199
+ confidence: high
200
+ source: shai-hulud-v2
201
+ introduced: "2025-11-01"
202
+ description: "Package compromis par Shai-Hulud v2 - inclut dead man's switch"
203
+ references:
204
+ - https://www.wiz.io/blog/shai-hulud-npm-supply-chain-attack
205
+ mitre: T1195.002
206
+
207
+ - id: SHAI-HULUD-V2-001c
208
+ name: "@asyncapi/specs"
209
+ version: "6.9.1"
210
+ severity: critical
211
+ confidence: high
212
+ source: shai-hulud-v2
213
+ introduced: "2025-11-01"
214
+ description: "Package compromis par Shai-Hulud v2 - inclut dead man's switch"
215
+ references:
216
+ - https://www.wiz.io/blog/shai-hulud-npm-supply-chain-attack
217
+ mitre: T1195.002
218
+
219
+ - id: SHAI-HULUD-V2-001d
220
+ name: "@asyncapi/specs"
221
+ version: "6.10.1"
54
222
  severity: critical
55
223
  confidence: high
56
224
  source: shai-hulud-v2
@@ -62,7 +230,7 @@ packages:
62
230
 
63
231
  - id: SHAI-HULUD-V2-002
64
232
  name: "get-them-args"
65
- version: "*"
233
+ version: "1.3.3"
66
234
  severity: critical
67
235
  confidence: high
68
236
  source: shai-hulud-v2
@@ -72,9 +240,21 @@ packages:
72
240
  - https://www.wiz.io/blog/shai-hulud-npm-supply-chain-attack
73
241
  mitre: T1195.002
74
242
 
75
- - id: SHAI-HULUD-V2-003
243
+ - id: SHAI-HULUD-V2-003a
76
244
  name: "kill-port"
77
- version: "*"
245
+ version: "2.0.2"
246
+ severity: critical
247
+ confidence: high
248
+ source: shai-hulud-v2
249
+ introduced: "2025-11-01"
250
+ description: "Package compromis par Shai-Hulud v2"
251
+ references:
252
+ - https://www.wiz.io/blog/shai-hulud-npm-supply-chain-attack
253
+ mitre: T1195.002
254
+
255
+ - id: SHAI-HULUD-V2-003b
256
+ name: "kill-port"
257
+ version: "2.0.3"
78
258
  severity: critical
79
259
  confidence: high
80
260
  source: shai-hulud-v2
@@ -84,9 +264,33 @@ packages:
84
264
  - https://www.wiz.io/blog/shai-hulud-npm-supply-chain-attack
85
265
  mitre: T1195.002
86
266
 
87
- - id: SHAI-HULUD-V2-004
267
+ - id: SHAI-HULUD-V2-004a
88
268
  name: "posthog-node"
89
- version: "*"
269
+ version: "4.18.1"
270
+ severity: critical
271
+ confidence: high
272
+ source: shai-hulud-v2
273
+ introduced: "2025-11-01"
274
+ description: "Package compromis par Shai-Hulud v2"
275
+ references:
276
+ - https://www.wiz.io/blog/shai-hulud-npm-supply-chain-attack
277
+ mitre: T1195.002
278
+
279
+ - id: SHAI-HULUD-V2-004b
280
+ name: "posthog-node"
281
+ version: "5.11.3"
282
+ severity: critical
283
+ confidence: high
284
+ source: shai-hulud-v2
285
+ introduced: "2025-11-01"
286
+ description: "Package compromis par Shai-Hulud v2"
287
+ references:
288
+ - https://www.wiz.io/blog/shai-hulud-npm-supply-chain-attack
289
+ mitre: T1195.002
290
+
291
+ - id: SHAI-HULUD-V2-004c
292
+ name: "posthog-node"
293
+ version: "5.13.3"
90
294
  severity: critical
91
295
  confidence: high
92
296
  source: shai-hulud-v2
@@ -98,7 +302,7 @@ packages:
98
302
 
99
303
  - id: SHAI-HULUD-V2-005
100
304
  name: "posthog-js"
101
- version: "*"
305
+ version: "1.297.3"
102
306
  severity: critical
103
307
  confidence: high
104
308
  source: shai-hulud-v2
@@ -0,0 +1,20 @@
1
+ {
2
+ "target": "npm/evil-pkg@1.0.0",
3
+ "timestamp": "2026-03-06T13:25:09.667Z",
4
+ "ecosystem": "npm",
5
+ "summary": {
6
+ "critical": 1,
7
+ "high": 0,
8
+ "medium": 0,
9
+ "low": 0,
10
+ "total": 1,
11
+ "riskLevel": "CRITICAL",
12
+ "riskScore": 25
13
+ },
14
+ "threats": [
15
+ {
16
+ "type": "known_malicious_package",
17
+ "severity": "CRITICAL"
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "target": "npm/evil-pkg@1.0.0",
3
+ "timestamp": "2026-03-06T13:25:09.668Z",
4
+ "ecosystem": "npm",
5
+ "summary": {
6
+ "critical": 1,
7
+ "high": 0,
8
+ "medium": 0,
9
+ "low": 0,
10
+ "total": 1,
11
+ "riskLevel": "CRITICAL",
12
+ "riskScore": 25
13
+ },
14
+ "threats": [
15
+ {
16
+ "type": "known_malicious_package",
17
+ "severity": "CRITICAL"
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "target": "npm/suspect-pkg@1.0",
3
+ "timestamp": "2026-03-06T13:25:09.668Z",
4
+ "ecosystem": "npm",
5
+ "summary": {
6
+ "critical": 0,
7
+ "high": 1,
8
+ "medium": 0,
9
+ "low": 0,
10
+ "total": 1,
11
+ "riskLevel": "HIGH",
12
+ "riskScore": 15
13
+ },
14
+ "threats": [
15
+ {
16
+ "type": "dynamic_require",
17
+ "severity": "HIGH"
18
+ }
19
+ ],
20
+ "sandbox": {
21
+ "score": 75,
22
+ "severity": "HIGH"
23
+ }
24
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "target": "npm/evil-pkg@2.0.0",
3
+ "timestamp": "2026-03-06T13:25:10.228Z",
4
+ "ecosystem": "npm",
5
+ "summary": {
6
+ "critical": 1,
7
+ "high": 0,
8
+ "medium": 0,
9
+ "low": 0,
10
+ "total": 1,
11
+ "riskLevel": "CRITICAL",
12
+ "riskScore": 25
13
+ },
14
+ "threats": [
15
+ {
16
+ "type": "known_malicious_package",
17
+ "severity": "CRITICAL"
18
+ }
19
+ ],
20
+ "sandbox": {
21
+ "score": 85,
22
+ "severity": "CRITICAL"
23
+ }
24
+ }
@@ -0,0 +1,61 @@
1
+ {
2
+ "date": "2026-03-06",
3
+ "timestamp": "2026-03-06T13:25:10.394Z",
4
+ "embed": {
5
+ "embeds": [
6
+ {
7
+ "title": "📊 MUAD'DIB Daily Report",
8
+ "color": 3447003,
9
+ "fields": [
10
+ {
11
+ "name": "Packages Scanned",
12
+ "value": "3",
13
+ "inline": true
14
+ },
15
+ {
16
+ "name": "Clean",
17
+ "value": "1",
18
+ "inline": true
19
+ },
20
+ {
21
+ "name": "Suspects",
22
+ "value": "0",
23
+ "inline": true
24
+ },
25
+ {
26
+ "name": "Errors",
27
+ "value": "0",
28
+ "inline": true
29
+ },
30
+ {
31
+ "name": "Avg Scan Time",
32
+ "value": "2.0s/pkg",
33
+ "inline": true
34
+ },
35
+ {
36
+ "name": "Top Suspects",
37
+ "value": "1. **npm/test-dedup-detection-1772803509664@1.0.0** — 1 finding(s)",
38
+ "inline": false
39
+ }
40
+ ],
41
+ "footer": {
42
+ "text": "MUAD'DIB - Daily summary | 2026-03-06 13:25:10 UTC"
43
+ },
44
+ "timestamp": "2026-03-06T13:25:10.394Z"
45
+ }
46
+ ]
47
+ },
48
+ "metrics": {
49
+ "scanned": 3,
50
+ "clean": 1,
51
+ "suspect": 0,
52
+ "errors": 0,
53
+ "avgScanTimeMs": 2000,
54
+ "suspectByTier": {
55
+ "t1": 0,
56
+ "t2": 0,
57
+ "t3": 0
58
+ },
59
+ "topSuspects": []
60
+ }
61
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muaddib-scanner",
3
- "version": "2.5.6",
3
+ "version": "2.5.8",
4
4
  "description": "Supply-chain threat detection & response for npm & PyPI/Python",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -958,7 +958,7 @@ async function scrapeSnykMalware() {
958
958
  { name: 'event-stream', version: '3.3.6', description: 'Flatmap-stream backdoor (2018)' },
959
959
  { name: 'flatmap-stream', version: '*', description: 'Malicious dependency of event-stream' },
960
960
  { name: 'eslint-scope', version: '3.7.2', description: 'Credential theft (2018)' },
961
- { name: 'eslint-config-eslint', version: '*', description: 'Credential theft (2018)' },
961
+ { name: 'eslint-config-eslint', version: '5.0.2', description: 'Credential theft (2018)' },
962
962
  { name: 'getcookies', version: '*', description: 'Backdoor malware' },
963
963
  { name: 'mailparser', version: '2.3.0', description: 'Compromised version' },
964
964
  { name: 'node-ipc', version: '10.1.1', description: 'Protestware - file deletion' },
@@ -162,7 +162,12 @@ function analyzePreloadLog(logContent) {
162
162
  }
163
163
 
164
164
  // ── Rule 5: Suspicious exec ──
165
- const dangerousExecLines = execLines.filter(l => l.includes('DANGEROUS'));
165
+ const dangerousExecLines = execLines.filter(l => {
166
+ if (!l.includes('DANGEROUS')) return false;
167
+ // Skip sandbox infrastructure commands (e.g. /usr/bin/timeout wrapping node)
168
+ if (/\btimeout\b/.test(l)) return false;
169
+ return true;
170
+ });
166
171
  if (dangerousExecLines.length > 0) {
167
172
  const cmds = dangerousExecLines.map(l => {
168
173
  const m = l.match(/(?:exec|execSync|spawn|spawnSync|execFile|execFileSync):\s*(.+?)(?:\s+\(t\+|$)/);
@@ -46,6 +46,9 @@ const PROBE_PORTS = [65535]; // Node.js internal connectivity checks
46
46
  // Commands that are always suspicious in a sandbox
47
47
  const DANGEROUS_CMDS = ['curl', 'wget', 'nc', 'netcat', 'python', 'python3', 'bash', 'sh'];
48
48
 
49
+ // Commands that are sandbox infrastructure — not spawned by the package
50
+ const SAFE_SANDBOX_CMDS = new Set(['timeout', 'node', 'npm', 'npx', 'su', 'env']);
51
+
49
52
  // Static canary tokens injected by sandbox-runner.sh (fallback honeypots).
50
53
  // These are searched in the sandbox report as a complement to the dynamic
51
54
  // tokens from canary-tokens.js (which use random suffixes per session).
@@ -607,6 +610,7 @@ function scoreFindings(report) {
607
610
  for (const p of (report.processes?.spawned || [])) {
608
611
  const cmd = p.command || '';
609
612
  const basename = path.basename(cmd);
613
+ if (SAFE_SANDBOX_CMDS.has(basename)) continue; // Skip sandbox infrastructure
610
614
  if (DANGEROUS_CMDS.some(d => basename === d)) {
611
615
  score += 40;
612
616
  findings.push({ type: 'suspicious_process', severity: 'CRITICAL', detail: `Dangerous command spawned: ${cmd}`, evidence: cmd });
@@ -762,4 +766,4 @@ function displayResults(result) {
762
766
  }
763
767
  }
764
768
 
765
- module.exports = { buildSandboxImage, runSandbox, runSingleSandbox, scoreFindings, generateNetworkReport, EXFIL_PATTERNS, SAFE_DOMAINS, getSeverity, displayResults, isDockerAvailable, imageExists, STATIC_CANARY_TOKENS, detectStaticCanaryExfiltration, analyzePreloadLog, TIME_OFFSETS };
769
+ module.exports = { buildSandboxImage, runSandbox, runSingleSandbox, scoreFindings, generateNetworkReport, EXFIL_PATTERNS, SAFE_DOMAINS, getSeverity, displayResults, isDockerAvailable, imageExists, STATIC_CANARY_TOKENS, detectStaticCanaryExfiltration, analyzePreloadLog, TIME_OFFSETS, SAFE_SANDBOX_CMDS };
@@ -56,6 +56,14 @@ const SAFE_STRINGS = [
56
56
  'npmjs.com'
57
57
  ];
58
58
 
59
+ // Domains where fetch is legitimate (not C2) — used to suppress download_exec_binary compound
60
+ const SAFE_FETCH_DOMAINS = [
61
+ 'registry.npmjs.org', 'npmjs.com',
62
+ 'github.com', 'objects.githubusercontent.com', 'raw.githubusercontent.com',
63
+ 'nodejs.org', 'yarnpkg.com',
64
+ 'pypi.org', 'files.pythonhosted.org'
65
+ ];
66
+
59
67
  // Credential-stealing CLI commands (s1ngularity/Nx, Shai-Hulud)
60
68
  const CREDENTIAL_CLI_COMMANDS = [
61
69
  'gh auth token',
@@ -1182,15 +1190,22 @@ function handleLiteral(node, ctx) {
1182
1190
  }
1183
1191
  }
1184
1192
 
1185
- // Detect AI agent dangerous flags as string literals
1193
+ // Detect AI agent dangerous flags as string literals (MEDIUM signal only —
1194
+ // CRITICAL reserved for CallExpression context where flag is actually used in exec/spawn)
1186
1195
  for (const flag of AI_AGENT_DANGEROUS_FLAGS) {
1187
1196
  if (node.value === flag) {
1188
- ctx.threats.push({
1189
- type: 'ai_agent_abuse',
1190
- severity: 'CRITICAL',
1191
- message: `AI agent security bypass flag "${flag}" found — weaponized AI coding assistant (s1ngularity/Nx pattern).`,
1192
- file: ctx.relFile
1193
- });
1197
+ // Skip if already detected in a CallExpression context (avoid double-counting)
1198
+ const alreadyDetected = ctx.threats.some(t =>
1199
+ t.type === 'ai_agent_abuse' && t.severity === 'CRITICAL' && t.file === ctx.relFile
1200
+ );
1201
+ if (!alreadyDetected) {
1202
+ ctx.threats.push({
1203
+ type: 'ai_agent_abuse',
1204
+ severity: 'MEDIUM',
1205
+ message: `AI agent security bypass flag "${flag}" referenced in code — verify it is not used in exec/spawn invocations.`,
1206
+ file: ctx.relFile
1207
+ });
1208
+ }
1194
1209
  }
1195
1210
  }
1196
1211
 
@@ -1495,7 +1510,8 @@ function handlePostWalk(ctx) {
1495
1510
  }
1496
1511
 
1497
1512
  // Wave 4: Download-execute-cleanup — https download + chmod executable + execSync + unlink
1498
- if (ctx.hasRemoteFetch && ctx.hasChmodExecutable && ctx.hasExecSyncCall) {
1513
+ // Exclude when all URLs in the file point to safe registries (npm, GitHub, nodejs.org)
1514
+ if (ctx.hasRemoteFetch && ctx.hasChmodExecutable && ctx.hasExecSyncCall && !ctx.fetchOnlySafeDomains) {
1499
1515
  ctx.threats.push({
1500
1516
  type: 'download_exec_binary',
1501
1517
  severity: 'CRITICAL',