muaddib-scanner 1.0.9 → 1.0.11
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/.muaddib-cache/iocs.json +355 -0
- package/package.json +3 -3
- package/rapport.html +159 -0
- package/src/scanner/ast.js +45 -14
- package/src/scanner/dataflow.js +39 -11
- package/src/scanner/typosquat.js +97 -140
- package/.github/workflows/scan.yml +0 -33
- package/CONTRIBUTING.md +0 -98
- package/docs/threat-model.md +0 -116
- package/test/samples/malicious.js +0 -20
- package/tests/run-tests.js +0 -389
- package/tests/samples/ast/malicious.js +0 -20
- package/tests/samples/clean/safe.js +0 -14
- package/tests/samples/dataflow/exfiltration.js +0 -20
- package/tests/samples/edge/empty/empty.js +0 -0
- package/tests/samples/edge/invalid-syntax/broken.js +0 -5
- package/tests/samples/edge/large-file/large.js +0 -6
- package/tests/samples/edge/non-js/readme.txt +0 -3
- package/tests/samples/markers/shai-hulud.js +0 -10
- package/tests/samples/obfuscation/obfuscated.js +0 -1
- package/tests/samples/package/package.json +0 -9
- package/tests/samples/shell/malicious.sh +0 -13
- package/tests/samples/typosquat/package.json +0 -11
- package/vscode-extension/.vscode/launch.json +0 -13
- package/vscode-extension/.vscodeignore +0 -0
- package/vscode-extension/LICENSE +0 -21
- package/vscode-extension/README.md +0 -0
- package/vscode-extension/extension.js +0 -271
- package/vscode-extension/icon.png +0 -0
- package/vscode-extension/muaddib-vscode-1.0.0.vsix +0 -0
- package/vscode-extension/package.json +0 -69
- package/vscode-extension/vscode-extension/README.md +0 -44
- package/vscode-extension/vscode-extension/package.json +0 -64
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
{
|
|
2
|
+
"packages": [
|
|
3
|
+
{
|
|
4
|
+
"name": "@ctrl/tinycolor",
|
|
5
|
+
"version": "4.1.1",
|
|
6
|
+
"source": "shai-hulud-v1"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "ng2-file-upload",
|
|
10
|
+
"version": "*",
|
|
11
|
+
"source": "shai-hulud-v1"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "ngx-bootstrap",
|
|
15
|
+
"version": "*",
|
|
16
|
+
"source": "shai-hulud-v1"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "@asyncapi/specs",
|
|
20
|
+
"version": "*",
|
|
21
|
+
"source": "shai-hulud-v2"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "@asyncapi/openapi-schema-parser",
|
|
25
|
+
"version": "*",
|
|
26
|
+
"source": "shai-hulud-v2"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "get-them-args",
|
|
30
|
+
"version": "*",
|
|
31
|
+
"source": "shai-hulud-v2"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "kill-port",
|
|
35
|
+
"version": "*",
|
|
36
|
+
"source": "shai-hulud-v2"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "shell-exec",
|
|
40
|
+
"version": "*",
|
|
41
|
+
"source": "shai-hulud-v2"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "posthog-node",
|
|
45
|
+
"version": "*",
|
|
46
|
+
"source": "shai-hulud-v2"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "posthog-js",
|
|
50
|
+
"version": "*",
|
|
51
|
+
"source": "shai-hulud-v2"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "@postman/tunnel-agent",
|
|
55
|
+
"version": "*",
|
|
56
|
+
"source": "shai-hulud-v2"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "@zapier/secret-scrubber",
|
|
60
|
+
"version": "*",
|
|
61
|
+
"source": "shai-hulud-v2"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "@vietmoney/react-big-calendar",
|
|
65
|
+
"version": "0.26.2",
|
|
66
|
+
"source": "shai-hulud-v3"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "flatmap-stream",
|
|
70
|
+
"version": "0.1.1",
|
|
71
|
+
"source": "event-stream-2018"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "event-stream",
|
|
75
|
+
"version": "3.3.6",
|
|
76
|
+
"source": "event-stream-2018"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "eslint-scope",
|
|
80
|
+
"version": "3.7.2",
|
|
81
|
+
"source": "eslint-scope-2018"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "eslint-config-prettier",
|
|
85
|
+
"version": "8.10.1",
|
|
86
|
+
"source": "eslint-prettier-2025"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "eslint-config-prettier",
|
|
90
|
+
"version": "9.1.1",
|
|
91
|
+
"source": "eslint-prettier-2025"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "eslint-plugin-prettier",
|
|
95
|
+
"version": "4.2.2",
|
|
96
|
+
"source": "eslint-prettier-2025"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "synckit",
|
|
100
|
+
"version": "0.11.9",
|
|
101
|
+
"source": "eslint-prettier-2025"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "@pkgr/core",
|
|
105
|
+
"version": "0.2.8",
|
|
106
|
+
"source": "eslint-prettier-2025"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "napi-postinstall",
|
|
110
|
+
"version": "0.3.1",
|
|
111
|
+
"source": "eslint-prettier-2025"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "got-fetch",
|
|
115
|
+
"version": "5.1.11",
|
|
116
|
+
"source": "eslint-prettier-2025"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"name": "is",
|
|
120
|
+
"version": "3.3.1",
|
|
121
|
+
"source": "is-package-2025"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "is",
|
|
125
|
+
"version": "5.0.0",
|
|
126
|
+
"source": "is-package-2025"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "crossenv",
|
|
130
|
+
"version": "*",
|
|
131
|
+
"source": "typosquat"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"name": "cross-env.js",
|
|
135
|
+
"version": "*",
|
|
136
|
+
"source": "typosquat"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"name": "mongose",
|
|
140
|
+
"version": "*",
|
|
141
|
+
"source": "typosquat"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"name": "mssql.js",
|
|
145
|
+
"version": "*",
|
|
146
|
+
"source": "typosquat"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"name": "mssql-node",
|
|
150
|
+
"version": "*",
|
|
151
|
+
"source": "typosquat"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"name": "babelcli",
|
|
155
|
+
"version": "*",
|
|
156
|
+
"source": "typosquat"
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"name": "http-proxy.js",
|
|
160
|
+
"version": "*",
|
|
161
|
+
"source": "typosquat"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"name": "proxy.js",
|
|
165
|
+
"version": "*",
|
|
166
|
+
"source": "typosquat"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"name": "shadowsock",
|
|
170
|
+
"version": "*",
|
|
171
|
+
"source": "typosquat"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"name": "smb",
|
|
175
|
+
"version": "*",
|
|
176
|
+
"source": "typosquat"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"name": "nodesass",
|
|
180
|
+
"version": "*",
|
|
181
|
+
"source": "typosquat"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"name": "node-sass.js",
|
|
185
|
+
"version": "*",
|
|
186
|
+
"source": "typosquat"
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"name": "node-ipc",
|
|
190
|
+
"version": "10.1.1",
|
|
191
|
+
"source": "protestware"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"name": "node-ipc",
|
|
195
|
+
"version": "10.1.2",
|
|
196
|
+
"source": "protestware"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"name": "node-ipc",
|
|
200
|
+
"version": "10.1.3",
|
|
201
|
+
"source": "protestware"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"name": "colors",
|
|
205
|
+
"version": "1.4.1",
|
|
206
|
+
"source": "protestware"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"name": "colors",
|
|
210
|
+
"version": "1.4.2",
|
|
211
|
+
"source": "protestware"
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"name": "faker",
|
|
215
|
+
"version": "6.6.6",
|
|
216
|
+
"source": "protestware"
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"name": "ua-parser-js",
|
|
220
|
+
"version": "0.7.29",
|
|
221
|
+
"source": "community",
|
|
222
|
+
"description": "Compromis octobre 2021 - crypto miner"
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"name": "coa",
|
|
226
|
+
"version": "2.0.3",
|
|
227
|
+
"source": "community",
|
|
228
|
+
"description": "Compromis novembre 2021"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"name": "coa",
|
|
232
|
+
"version": "2.0.4",
|
|
233
|
+
"source": "community",
|
|
234
|
+
"description": "Compromis novembre 2021"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"name": "rc",
|
|
238
|
+
"version": "1.2.9",
|
|
239
|
+
"source": "community",
|
|
240
|
+
"description": "Compromis novembre 2021"
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"name": "rc",
|
|
244
|
+
"version": "1.3.9",
|
|
245
|
+
"source": "community",
|
|
246
|
+
"description": "Compromis novembre 2021"
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"name": "left-pad",
|
|
250
|
+
"version": "*",
|
|
251
|
+
"source": "community",
|
|
252
|
+
"description": "Incident 2016 - supply chain"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"name": "lodash-merge",
|
|
256
|
+
"version": "*",
|
|
257
|
+
"source": "typosquat",
|
|
258
|
+
"description": "Typosquat de lodash.merge"
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"name": "loadash",
|
|
262
|
+
"version": "*",
|
|
263
|
+
"source": "typosquat",
|
|
264
|
+
"description": "Typosquat de lodash"
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
"name": "electorn",
|
|
268
|
+
"version": "*",
|
|
269
|
+
"source": "typosquat",
|
|
270
|
+
"description": "Typosquat de electron"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"name": "discord.js-selfbot-v11",
|
|
274
|
+
"version": "*",
|
|
275
|
+
"source": "community",
|
|
276
|
+
"description": "Token stealer Discord"
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"name": "discord-selfbot-tools",
|
|
280
|
+
"version": "*",
|
|
281
|
+
"source": "community",
|
|
282
|
+
"description": "Token stealer Discord"
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"name": "discordsystem",
|
|
286
|
+
"version": "*",
|
|
287
|
+
"source": "community",
|
|
288
|
+
"description": "Token stealer Discord"
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"name": "discord-lofy",
|
|
292
|
+
"version": "*",
|
|
293
|
+
"source": "community",
|
|
294
|
+
"description": "Token stealer Discord"
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
"name": "prerequests",
|
|
298
|
+
"version": "*",
|
|
299
|
+
"source": "typosquat",
|
|
300
|
+
"description": "Typosquat de prerequests"
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"name": "requstes",
|
|
304
|
+
"version": "*",
|
|
305
|
+
"source": "typosquat",
|
|
306
|
+
"description": "Typosquat de requests"
|
|
307
|
+
}
|
|
308
|
+
],
|
|
309
|
+
"files": [
|
|
310
|
+
"setup_bun.js",
|
|
311
|
+
"bun_environment.js",
|
|
312
|
+
"bundle.js",
|
|
313
|
+
"node-gyp.dll",
|
|
314
|
+
"preinstall.js",
|
|
315
|
+
"postinstall.js",
|
|
316
|
+
"install.js",
|
|
317
|
+
"discord-webhook.js",
|
|
318
|
+
"token-grabber.js",
|
|
319
|
+
"stealer.js",
|
|
320
|
+
"inject.js"
|
|
321
|
+
],
|
|
322
|
+
"hashes": [
|
|
323
|
+
"62ee164b9b306250c1172583f138c9614139264f889fa99614903c12755468d0",
|
|
324
|
+
"cbb9bc5a8496243e02f3cc080efbe3e4a1430ba0671f2e43a202bf45b05479cd",
|
|
325
|
+
"f099c5d9ec417d4445a0328ac0ada9cde79fc37410914103ae9c609cbc0ee068",
|
|
326
|
+
"a3894003ad1d293ba96d77881ccd2071446dc3f65f434669b49b3da92421901a",
|
|
327
|
+
"f1df4896244500671eb4aa63ebb48ea11cee196fafaa0e9874e17b24ac053c02",
|
|
328
|
+
"9d59fd0bcc14b671079824c704575f201b74276238dc07a9c12a93a84195648a",
|
|
329
|
+
"e0250076c1d2ac38777ea8f542431daf61fcbaab0ca9c196614b28065ef5b918",
|
|
330
|
+
"6c9628f72d2bb789fe8f097a611d61c8c53f2f21e47c6a5d8d3e0e0b8e5e8c8f",
|
|
331
|
+
"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
|
|
332
|
+
"4b2399646573bb737c4969563303d8ee2e9ddbd1b271f1ca9e35ea78062538db",
|
|
333
|
+
"46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09",
|
|
334
|
+
"b74caeaa75e077c99f7d44f46daaf9796a3be43ecf24f2a1fd381844669da777",
|
|
335
|
+
"dc67467a39b70d1cd4c1f7f7a459b35058163592f4a9e8fb4dffcbba98ef210c",
|
|
336
|
+
"8f3c4e2a1b5d6c7e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e",
|
|
337
|
+
"1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
|
|
338
|
+
],
|
|
339
|
+
"markers": [
|
|
340
|
+
"Sha1-Hulud",
|
|
341
|
+
"Shai-Hulud",
|
|
342
|
+
"The Second Coming",
|
|
343
|
+
"Goldox-T3chs",
|
|
344
|
+
"Only Happy Girl",
|
|
345
|
+
"peacenotwar",
|
|
346
|
+
"protestware",
|
|
347
|
+
"/dev/tcp",
|
|
348
|
+
"reverse shell",
|
|
349
|
+
"discord.com/api/webhooks",
|
|
350
|
+
"token grabber",
|
|
351
|
+
"crypto miner",
|
|
352
|
+
"xmrig"
|
|
353
|
+
],
|
|
354
|
+
"updated": "2026-01-02T09:21:30.216Z"
|
|
355
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "muaddib-scanner",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "Supply-chain threat detection & response for npm",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"muaddib": "
|
|
7
|
+
"muaddib": "bin/muaddib.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "node tests/run-tests.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"license": "MIT",
|
|
27
27
|
"repository": {
|
|
28
28
|
"type": "git",
|
|
29
|
-
"url": "https://github.com/DNSZLSK/muad-dib.git"
|
|
29
|
+
"url": "git+https://github.com/DNSZLSK/muad-dib.git"
|
|
30
30
|
},
|
|
31
31
|
"homepage": "https://github.com/DNSZLSK/muad-dib",
|
|
32
32
|
"bugs": {
|
package/rapport.html
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="fr">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>MUAD'DIB - Rapport de scan</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
10
|
+
background: #1a1a2e;
|
|
11
|
+
color: #eee;
|
|
12
|
+
margin: 0;
|
|
13
|
+
padding: 20px;
|
|
14
|
+
}
|
|
15
|
+
.container {
|
|
16
|
+
max-width: 1200px;
|
|
17
|
+
margin: 0 auto;
|
|
18
|
+
}
|
|
19
|
+
h1 {
|
|
20
|
+
color: #e94560;
|
|
21
|
+
border-bottom: 2px solid #e94560;
|
|
22
|
+
padding-bottom: 10px;
|
|
23
|
+
}
|
|
24
|
+
.summary {
|
|
25
|
+
display: flex;
|
|
26
|
+
gap: 20px;
|
|
27
|
+
margin: 20px 0;
|
|
28
|
+
}
|
|
29
|
+
.summary-card {
|
|
30
|
+
background: #16213e;
|
|
31
|
+
padding: 20px;
|
|
32
|
+
border-radius: 8px;
|
|
33
|
+
flex: 1;
|
|
34
|
+
}
|
|
35
|
+
.summary-card h3 {
|
|
36
|
+
margin: 0 0 10px 0;
|
|
37
|
+
color: #888;
|
|
38
|
+
font-size: 14px;
|
|
39
|
+
}
|
|
40
|
+
.summary-card .value {
|
|
41
|
+
font-size: 32px;
|
|
42
|
+
font-weight: bold;
|
|
43
|
+
}
|
|
44
|
+
.critical .value { color: #e94560; }
|
|
45
|
+
.high .value { color: #ff6b35; }
|
|
46
|
+
.medium .value { color: #f9c74f; }
|
|
47
|
+
.total .value { color: #4ecdc4; }
|
|
48
|
+
table {
|
|
49
|
+
width: 100%;
|
|
50
|
+
border-collapse: collapse;
|
|
51
|
+
margin-top: 20px;
|
|
52
|
+
}
|
|
53
|
+
th, td {
|
|
54
|
+
padding: 12px;
|
|
55
|
+
text-align: left;
|
|
56
|
+
border-bottom: 1px solid #333;
|
|
57
|
+
}
|
|
58
|
+
th {
|
|
59
|
+
background: #16213e;
|
|
60
|
+
color: #e94560;
|
|
61
|
+
}
|
|
62
|
+
tr.critical { background: rgba(233, 69, 96, 0.2); }
|
|
63
|
+
tr.high { background: rgba(255, 107, 53, 0.2); }
|
|
64
|
+
tr.medium { background: rgba(249, 199, 79, 0.1); }
|
|
65
|
+
.meta {
|
|
66
|
+
color: #666;
|
|
67
|
+
font-size: 12px;
|
|
68
|
+
margin-top: 40px;
|
|
69
|
+
}
|
|
70
|
+
.ok {
|
|
71
|
+
background: #16213e;
|
|
72
|
+
padding: 40px;
|
|
73
|
+
border-radius: 8px;
|
|
74
|
+
text-align: center;
|
|
75
|
+
color: #4ecdc4;
|
|
76
|
+
font-size: 24px;
|
|
77
|
+
}
|
|
78
|
+
</style>
|
|
79
|
+
</head>
|
|
80
|
+
<body>
|
|
81
|
+
<div class="container">
|
|
82
|
+
<h1>MUAD'DIB - Rapport de scan</h1>
|
|
83
|
+
|
|
84
|
+
<div class="summary">
|
|
85
|
+
<div class="summary-card total">
|
|
86
|
+
<h3>TOTAL</h3>
|
|
87
|
+
<div class="value">4</div>
|
|
88
|
+
</div>
|
|
89
|
+
<div class="summary-card critical">
|
|
90
|
+
<h3>CRITICAL</h3>
|
|
91
|
+
<div class="value">0</div>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="summary-card high">
|
|
94
|
+
<h3>HIGH</h3>
|
|
95
|
+
<div class="value">3</div>
|
|
96
|
+
</div>
|
|
97
|
+
<div class="summary-card medium">
|
|
98
|
+
<h3>MEDIUM</h3>
|
|
99
|
+
<div class="value">1</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
<table>
|
|
105
|
+
<thead>
|
|
106
|
+
<tr>
|
|
107
|
+
<th>Severite</th>
|
|
108
|
+
<th>Type</th>
|
|
109
|
+
<th>Message</th>
|
|
110
|
+
<th>Fichier</th>
|
|
111
|
+
<th>Recommandation</th>
|
|
112
|
+
</tr>
|
|
113
|
+
</thead>
|
|
114
|
+
<tbody>
|
|
115
|
+
|
|
116
|
+
<tr class="high">
|
|
117
|
+
<td>HIGH</td>
|
|
118
|
+
<td>sensitive_string</td>
|
|
119
|
+
<td>Reference a ".npmrc" detectee.</td>
|
|
120
|
+
<td>malicious.js</td>
|
|
121
|
+
<td>Reference a un chemin ou identifiant sensible. Verifier le contexte d'utilisation.</td>
|
|
122
|
+
</tr>
|
|
123
|
+
|
|
124
|
+
<tr class="high">
|
|
125
|
+
<td>HIGH</td>
|
|
126
|
+
<td>env_access</td>
|
|
127
|
+
<td>Acces a variable sensible process.env.GITHUB_TOKEN.</td>
|
|
128
|
+
<td>malicious.js</td>
|
|
129
|
+
<td>Acces a une variable d'environnement sensible. Verifier si les donnees sont exfiltrees.</td>
|
|
130
|
+
</tr>
|
|
131
|
+
|
|
132
|
+
<tr class="high">
|
|
133
|
+
<td>HIGH</td>
|
|
134
|
+
<td>sensitive_string</td>
|
|
135
|
+
<td>Reference a "api.github.com" detectee.</td>
|
|
136
|
+
<td>malicious.js</td>
|
|
137
|
+
<td>Reference a un chemin ou identifiant sensible. Verifier le contexte d'utilisation.</td>
|
|
138
|
+
</tr>
|
|
139
|
+
|
|
140
|
+
<tr class="medium">
|
|
141
|
+
<td>MEDIUM</td>
|
|
142
|
+
<td>dangerous_call_exec</td>
|
|
143
|
+
<td>Appel dangereux "exec" detecte.</td>
|
|
144
|
+
<td>malicious.js</td>
|
|
145
|
+
<td>Execution de commande systeme. Verifier les arguments passes.</td>
|
|
146
|
+
</tr>
|
|
147
|
+
|
|
148
|
+
</tbody>
|
|
149
|
+
</table>
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
<div class="meta">
|
|
153
|
+
<p>Cible: test/samples</p>
|
|
154
|
+
<p>Date: 2026-01-01T20:11:35.775Z</p>
|
|
155
|
+
<p>Genere par MUAD'DIB</p>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</body>
|
|
159
|
+
</html>
|
package/src/scanner/ast.js
CHANGED
|
@@ -11,29 +11,32 @@ const EXCLUDED_FILES = [
|
|
|
11
11
|
'src/response/playbooks.js'
|
|
12
12
|
];
|
|
13
13
|
|
|
14
|
-
const EXCLUDED_DIRS = [
|
|
14
|
+
const EXCLUDED_DIRS = [
|
|
15
|
+
'test', 'tests', 'node_modules', '.git', 'src', 'vscode-extension',
|
|
16
|
+
'scripts', 'bin', 'tools', 'build', 'dist', 'fixtures', 'examples',
|
|
17
|
+
'__tests__', '__mocks__', 'benchmark', 'benchmarks', 'docs', 'doc'
|
|
18
|
+
];
|
|
15
19
|
|
|
16
20
|
const DANGEROUS_CALLS = [
|
|
17
21
|
'eval',
|
|
18
|
-
'Function'
|
|
19
|
-
'exec',
|
|
20
|
-
'execSync',
|
|
21
|
-
'spawn',
|
|
22
|
-
'spawnSync'
|
|
22
|
+
'Function'
|
|
23
23
|
];
|
|
24
24
|
|
|
25
25
|
const SENSITIVE_STRINGS = [
|
|
26
26
|
'.npmrc',
|
|
27
27
|
'.ssh',
|
|
28
|
-
'GITHUB_TOKEN',
|
|
29
|
-
'NPM_TOKEN',
|
|
30
|
-
'AWS_SECRET',
|
|
31
|
-
'api.github.com',
|
|
32
28
|
'Shai-Hulud',
|
|
33
29
|
'The Second Coming',
|
|
34
30
|
'Goldox-T3chs'
|
|
35
31
|
];
|
|
36
32
|
|
|
33
|
+
// Strings qui ne sont PAS suspects
|
|
34
|
+
const SAFE_STRINGS = [
|
|
35
|
+
'api.github.com',
|
|
36
|
+
'registry.npmjs.org',
|
|
37
|
+
'npmjs.com'
|
|
38
|
+
];
|
|
39
|
+
|
|
37
40
|
async function analyzeAST(targetPath) {
|
|
38
41
|
const threats = [];
|
|
39
42
|
const files = findJsFiles(targetPath);
|
|
@@ -45,6 +48,11 @@ async function analyzeAST(targetPath) {
|
|
|
45
48
|
continue;
|
|
46
49
|
}
|
|
47
50
|
|
|
51
|
+
// Ignorer les fichiers dans les dossiers de dev
|
|
52
|
+
if (isDevFile(relativePath)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
const content = fs.readFileSync(file, 'utf8');
|
|
49
57
|
const fileThreats = analyzeFile(content, file, targetPath);
|
|
50
58
|
threats.push(...fileThreats);
|
|
@@ -53,6 +61,27 @@ async function analyzeAST(targetPath) {
|
|
|
53
61
|
return threats;
|
|
54
62
|
}
|
|
55
63
|
|
|
64
|
+
function isDevFile(relativePath) {
|
|
65
|
+
const devPatterns = [
|
|
66
|
+
/^scripts\//,
|
|
67
|
+
/^bin\//,
|
|
68
|
+
/^tools\//,
|
|
69
|
+
/^build\//,
|
|
70
|
+
/^fixtures\//,
|
|
71
|
+
/^examples\//,
|
|
72
|
+
/^__tests__\//,
|
|
73
|
+
/^__mocks__\//,
|
|
74
|
+
/^benchmark/,
|
|
75
|
+
/^docs?\//,
|
|
76
|
+
/\.test\.js$/,
|
|
77
|
+
/\.spec\.js$/,
|
|
78
|
+
/test\.js$/,
|
|
79
|
+
/spec\.js$/
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
return devPatterns.some(pattern => pattern.test(relativePath));
|
|
83
|
+
}
|
|
84
|
+
|
|
56
85
|
function analyzeFile(content, filePath, basePath) {
|
|
57
86
|
const threats = [];
|
|
58
87
|
let ast;
|
|
@@ -64,7 +93,6 @@ function analyzeFile(content, filePath, basePath) {
|
|
|
64
93
|
allowHashBang: true
|
|
65
94
|
});
|
|
66
95
|
} catch (e) {
|
|
67
|
-
// Fichier non parseable, peut etre obfusque
|
|
68
96
|
if (content.length > 1000 && content.split('\n').length < 10) {
|
|
69
97
|
threats.push({
|
|
70
98
|
type: 'possible_obfuscation',
|
|
@@ -76,7 +104,6 @@ function analyzeFile(content, filePath, basePath) {
|
|
|
76
104
|
return threats;
|
|
77
105
|
}
|
|
78
106
|
|
|
79
|
-
// Analyse des appels de fonction
|
|
80
107
|
walk.simple(ast, {
|
|
81
108
|
CallExpression(node) {
|
|
82
109
|
const callName = getCallName(node);
|
|
@@ -84,7 +111,7 @@ function analyzeFile(content, filePath, basePath) {
|
|
|
84
111
|
if (DANGEROUS_CALLS.includes(callName)) {
|
|
85
112
|
threats.push({
|
|
86
113
|
type: 'dangerous_call_' + callName.toLowerCase(),
|
|
87
|
-
severity:
|
|
114
|
+
severity: 'HIGH',
|
|
88
115
|
message: `Appel dangereux "${callName}" detecte.`,
|
|
89
116
|
file: path.relative(basePath, filePath)
|
|
90
117
|
});
|
|
@@ -104,6 +131,11 @@ function analyzeFile(content, filePath, basePath) {
|
|
|
104
131
|
|
|
105
132
|
Literal(node) {
|
|
106
133
|
if (typeof node.value === 'string') {
|
|
134
|
+
// Ignorer les strings safe
|
|
135
|
+
if (SAFE_STRINGS.some(s => node.value.includes(s))) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
107
139
|
for (const sensitive of SENSITIVE_STRINGS) {
|
|
108
140
|
if (node.value.includes(sensitive)) {
|
|
109
141
|
threats.push({
|
|
@@ -118,7 +150,6 @@ function analyzeFile(content, filePath, basePath) {
|
|
|
118
150
|
},
|
|
119
151
|
|
|
120
152
|
MemberExpression(node) {
|
|
121
|
-
// Detecte process.env.XXX
|
|
122
153
|
if (
|
|
123
154
|
node.object?.object?.name === 'process' &&
|
|
124
155
|
node.object?.property?.name === 'env'
|