@trailofbits/vsix-audit 0.1.0 → 0.1.2
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/dist/index.js +0 -0
- package/package.json +1 -1
- package/dist/scanner/checks/behavioral.d.ts +0 -3
- package/dist/scanner/checks/behavioral.d.ts.map +0 -1
- package/dist/scanner/checks/behavioral.js +0 -367
- package/dist/scanner/checks/behavioral.js.map +0 -1
- package/dist/scanner/checks/blocklist.d.ts +0 -3
- package/dist/scanner/checks/blocklist.d.ts.map +0 -1
- package/dist/scanner/checks/blocklist.js +0 -32
- package/dist/scanner/checks/blocklist.js.map +0 -1
- package/dist/scanner/checks/blocklist.test.d.ts +0 -2
- package/dist/scanner/checks/blocklist.test.d.ts.map +0 -1
- package/dist/scanner/checks/blocklist.test.js +0 -74
- package/dist/scanner/checks/blocklist.test.js.map +0 -1
- package/dist/scanner/checks/chains.d.ts +0 -35
- package/dist/scanner/checks/chains.d.ts.map +0 -1
- package/dist/scanner/checks/chains.js +0 -505
- package/dist/scanner/checks/chains.js.map +0 -1
- package/dist/scanner/checks/chains.test.d.ts +0 -2
- package/dist/scanner/checks/chains.test.d.ts.map +0 -1
- package/dist/scanner/checks/chains.test.js +0 -250
- package/dist/scanner/checks/chains.test.js.map +0 -1
- package/dist/scanner/checks/dataflow.d.ts +0 -3
- package/dist/scanner/checks/dataflow.d.ts.map +0 -1
- package/dist/scanner/checks/dataflow.js +0 -316
- package/dist/scanner/checks/dataflow.js.map +0 -1
- package/dist/scanner/checks/dependencies.d.ts +0 -13
- package/dist/scanner/checks/dependencies.d.ts.map +0 -1
- package/dist/scanner/checks/dependencies.js +0 -225
- package/dist/scanner/checks/dependencies.js.map +0 -1
- package/dist/scanner/checks/dependencies.test.d.ts +0 -2
- package/dist/scanner/checks/dependencies.test.d.ts.map +0 -1
- package/dist/scanner/checks/dependencies.test.js +0 -248
- package/dist/scanner/checks/dependencies.test.js.map +0 -1
- package/dist/scanner/checks/manifest.d.ts +0 -6
- package/dist/scanner/checks/manifest.d.ts.map +0 -1
- package/dist/scanner/checks/manifest.js +0 -123
- package/dist/scanner/checks/manifest.js.map +0 -1
- package/dist/scanner/checks/manifest.test.d.ts +0 -2
- package/dist/scanner/checks/manifest.test.d.ts.map +0 -1
- package/dist/scanner/checks/manifest.test.js +0 -108
- package/dist/scanner/checks/manifest.test.js.map +0 -1
- package/dist/scanner/checks/patterns.d.ts +0 -5
- package/dist/scanner/checks/patterns.d.ts.map +0 -1
- package/dist/scanner/checks/patterns.js +0 -251
- package/dist/scanner/checks/patterns.js.map +0 -1
- package/dist/scanner/checks/patterns.test.d.ts +0 -2
- package/dist/scanner/checks/patterns.test.d.ts.map +0 -1
- package/dist/scanner/checks/patterns.test.js +0 -147
- package/dist/scanner/checks/patterns.test.js.map +0 -1
- package/dist/scanner/checks/unicode.d.ts +0 -3
- package/dist/scanner/checks/unicode.d.ts.map +0 -1
- package/dist/scanner/checks/unicode.js +0 -247
- package/dist/scanner/checks/unicode.js.map +0 -1
- package/dist/scanner/checks/unicode.test.d.ts +0 -2
- package/dist/scanner/checks/unicode.test.d.ts.map +0 -1
- package/dist/scanner/checks/unicode.test.js +0 -202
- package/dist/scanner/checks/unicode.test.js.map +0 -1
package/dist/index.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"behavioral.d.ts","sourceRoot":"","sources":["../../../src/scanner/checks/behavioral.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAY,YAAY,EAAE,MAAM,aAAa,CAAC;AA6XnE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,EAAE,CAkDjE"}
|
|
@@ -1,367 +0,0 @@
|
|
|
1
|
-
import { isScannable, SCANNABLE_EXTENSIONS_PATTERN } from "../constants.js";
|
|
2
|
-
import { findLineNumberByIndex } from "../utils.js";
|
|
3
|
-
const SIGNATURES = [
|
|
4
|
-
{
|
|
5
|
-
id: "BEHAVIOR_CREDENTIAL_EXFIL",
|
|
6
|
-
title: "Credential exfiltration pattern",
|
|
7
|
-
description: "Code reads sensitive files, encodes the content, and sends it to an external server. This is the classic credential theft attack chain.",
|
|
8
|
-
severity: "critical",
|
|
9
|
-
stages: [
|
|
10
|
-
{
|
|
11
|
-
action: "file_read",
|
|
12
|
-
patterns: [
|
|
13
|
-
/readFile(?:Sync)?\s*\(/gi,
|
|
14
|
-
/fs\.promises\.readFile/gi,
|
|
15
|
-
/createReadStream\s*\(/gi,
|
|
16
|
-
],
|
|
17
|
-
description: "File read operation",
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
action: "encode",
|
|
21
|
-
patterns: [
|
|
22
|
-
/Buffer\.from\s*\([^)]+\)\.toString\s*\(\s*['"]base64/gi,
|
|
23
|
-
/btoa\s*\(/gi,
|
|
24
|
-
/\.toString\s*\(\s*['"](?:base64|hex)['"]\s*\)/gi,
|
|
25
|
-
/JSON\.stringify\s*\(/gi,
|
|
26
|
-
],
|
|
27
|
-
description: "Data encoding for transmission",
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
action: "network",
|
|
31
|
-
patterns: [
|
|
32
|
-
/fetch\s*\(/gi,
|
|
33
|
-
/axios\./gi,
|
|
34
|
-
/https?\.request/gi,
|
|
35
|
-
/\.post\s*\(/gi,
|
|
36
|
-
/\.send\s*\(/gi,
|
|
37
|
-
],
|
|
38
|
-
description: "Network transmission",
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
redFlags: [
|
|
42
|
-
"Reads from home directory or .ssh",
|
|
43
|
-
"Encodes before sending",
|
|
44
|
-
"Sends to external domain",
|
|
45
|
-
],
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
id: "BEHAVIOR_REVERSE_SHELL",
|
|
49
|
-
title: "Reverse shell pattern",
|
|
50
|
-
description: "Code establishes network connection and pipes input to command execution. This creates a remote shell for attackers.",
|
|
51
|
-
severity: "critical",
|
|
52
|
-
stages: [
|
|
53
|
-
{
|
|
54
|
-
action: "network",
|
|
55
|
-
patterns: [
|
|
56
|
-
/net\.Socket/gi,
|
|
57
|
-
/net\.connect/gi,
|
|
58
|
-
/net\.createConnection/gi,
|
|
59
|
-
/new\s+WebSocket/gi,
|
|
60
|
-
],
|
|
61
|
-
description: "Network connection",
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
action: "exec",
|
|
65
|
-
patterns: [/child_process/gi, /\.spawn\s*\(/gi, /\.exec\s*\(/gi, /process\.stdin/gi],
|
|
66
|
-
description: "Command execution",
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
maxSpan: 1500,
|
|
70
|
-
redFlags: ["Socket piped to shell", "Remote command execution"],
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
id: "BEHAVIOR_SUPPLY_CHAIN_ATTACK",
|
|
74
|
-
title: "Install script attack pattern",
|
|
75
|
-
description: "Package lifecycle script accesses environment, executes commands, and phones home. This is a supply chain attack pattern.",
|
|
76
|
-
severity: "high", // Downgraded - common in legitimate build tools
|
|
77
|
-
stages: [
|
|
78
|
-
{
|
|
79
|
-
action: "env_access",
|
|
80
|
-
patterns: [
|
|
81
|
-
/os\.homedir\s*\(\)/gi,
|
|
82
|
-
/os\.userInfo\s*\(\)/gi,
|
|
83
|
-
/process\.env\.(?:HOME|USERPROFILE|APPDATA)/gi,
|
|
84
|
-
],
|
|
85
|
-
description: "Home directory access",
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
action: "exec",
|
|
89
|
-
patterns: [/child_process\.exec\s*\(/gi, /execSync\s*\(/gi, /spawnSync\s*\(/gi],
|
|
90
|
-
description: "Command execution",
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
action: "network",
|
|
94
|
-
patterns: [/fetch\s*\(/gi, /axios\s*\./gi, /curl\s+/gi, /wget\s+/gi],
|
|
95
|
-
description: "Network activity",
|
|
96
|
-
},
|
|
97
|
-
],
|
|
98
|
-
minStages: 3, // Require all 3 stages to reduce false positives
|
|
99
|
-
maxSpan: 1000, // Tighter proximity requirement
|
|
100
|
-
legitimateUses: ["Build scripts", "Development tools"],
|
|
101
|
-
redFlags: ["Runs in postinstall", "Collects system info", "Sends to unknown domain"],
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
id: "BEHAVIOR_DROPPER",
|
|
105
|
-
title: "Malware dropper pattern",
|
|
106
|
-
description: "Code downloads content from remote URL, writes it to file, and executes it. This is a dropper/downloader pattern.",
|
|
107
|
-
severity: "critical",
|
|
108
|
-
stages: [
|
|
109
|
-
{
|
|
110
|
-
action: "download",
|
|
111
|
-
patterns: [
|
|
112
|
-
/fetch\s*\([^)]*https?:\/\//gi,
|
|
113
|
-
/axios\.get\s*\([^)]*https?:\/\//gi,
|
|
114
|
-
/https?\.get\s*\(/gi,
|
|
115
|
-
/request\s*\([^)]*https?:\/\//gi,
|
|
116
|
-
],
|
|
117
|
-
description: "Remote content download",
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
action: "file_read",
|
|
121
|
-
patterns: [
|
|
122
|
-
/writeFile(?:Sync)?\s*\(/gi,
|
|
123
|
-
/createWriteStream\s*\(/gi,
|
|
124
|
-
/fs\.promises\.writeFile/gi,
|
|
125
|
-
],
|
|
126
|
-
description: "File write",
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
action: "exec",
|
|
130
|
-
patterns: [/child_process/gi, /\.exec\s*\(/gi, /\.spawn\s*\(/gi, /execSync/gi],
|
|
131
|
-
description: "Execution",
|
|
132
|
-
},
|
|
133
|
-
],
|
|
134
|
-
maxSpan: 2000,
|
|
135
|
-
redFlags: [
|
|
136
|
-
"Downloads executable",
|
|
137
|
-
"Writes to temp or hidden location",
|
|
138
|
-
"Executes downloaded content",
|
|
139
|
-
],
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
id: "BEHAVIOR_KEYLOGGER",
|
|
143
|
-
title: "Keystroke capture pattern",
|
|
144
|
-
description: "Code captures keyboard/input events and stores or transmits the data. This indicates keylogging behavior.",
|
|
145
|
-
severity: "high",
|
|
146
|
-
stages: [
|
|
147
|
-
{
|
|
148
|
-
action: "clipboard",
|
|
149
|
-
patterns: [
|
|
150
|
-
// onDidChangeTextDocument is legitimate for language servers - don't flag it
|
|
151
|
-
// Instead, look for actual keystroke monitoring
|
|
152
|
-
/keyboard.*event/gi,
|
|
153
|
-
/keydown|keyup|keypress/gi,
|
|
154
|
-
/clipboard\.readText/gi,
|
|
155
|
-
/getSelection\s*\(\s*\)\.toString/gi,
|
|
156
|
-
],
|
|
157
|
-
description: "Keystroke/clipboard capture",
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
action: "persistence",
|
|
161
|
-
patterns: [
|
|
162
|
-
/globalState\.update/gi,
|
|
163
|
-
/writeFileSync?\s*\([^)]*keystroke/gi,
|
|
164
|
-
/localStorage\.setItem/gi,
|
|
165
|
-
],
|
|
166
|
-
description: "Data storage",
|
|
167
|
-
},
|
|
168
|
-
{
|
|
169
|
-
action: "network",
|
|
170
|
-
patterns: [/discord\.com\/api\/webhooks/gi, /discordapp\.com\/api\/webhooks/gi],
|
|
171
|
-
description: "Data exfiltration to Discord",
|
|
172
|
-
},
|
|
173
|
-
],
|
|
174
|
-
minStages: 2,
|
|
175
|
-
legitimateUses: ["Keyboard shortcut extensions"],
|
|
176
|
-
redFlags: ["Captures all keystrokes", "Sends to Discord webhook", "No user consent mechanism"],
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
id: "BEHAVIOR_CRYPTO_STEALER",
|
|
180
|
-
title: "Cryptocurrency stealer pattern",
|
|
181
|
-
description: "Code scans for wallet files, extracts keys/seeds, and exfiltrates them.",
|
|
182
|
-
severity: "critical",
|
|
183
|
-
stages: [
|
|
184
|
-
{
|
|
185
|
-
action: "file_read",
|
|
186
|
-
patterns: [
|
|
187
|
-
/\.ethereum/gi,
|
|
188
|
-
/\.bitcoin/gi,
|
|
189
|
-
/wallet\.dat/gi,
|
|
190
|
-
/keystore/gi,
|
|
191
|
-
/seed.*phrase/gi,
|
|
192
|
-
/mnemonic/gi,
|
|
193
|
-
],
|
|
194
|
-
description: "Wallet file access",
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
action: "encode",
|
|
198
|
-
patterns: [
|
|
199
|
-
/btoa\s*\(/gi, // More specific - require function call
|
|
200
|
-
/Buffer\.from\s*\([^)]*\)\.toString\s*\(\s*['"]base64/gi,
|
|
201
|
-
/toString\s*\(\s*['"](?:base64|hex)['"]\s*\)/gi,
|
|
202
|
-
],
|
|
203
|
-
description: "Data encoding for exfil",
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
action: "network",
|
|
207
|
-
patterns: [/discord.*webhook/gi, /\.post\s*\([^)]*wallet/gi],
|
|
208
|
-
description: "Exfiltration",
|
|
209
|
-
},
|
|
210
|
-
],
|
|
211
|
-
// Require all 3 stages - wallet access is the key indicator
|
|
212
|
-
minStages: 3,
|
|
213
|
-
maxSpan: 1500,
|
|
214
|
-
redFlags: [
|
|
215
|
-
"Scans for multiple wallet types",
|
|
216
|
-
"Extracts private keys",
|
|
217
|
-
"Sends to Discord/external",
|
|
218
|
-
],
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
id: "BEHAVIOR_PERSISTENCE",
|
|
222
|
-
title: "Persistence mechanism pattern",
|
|
223
|
-
description: "Code modifies startup files, schedules tasks, or installs itself for persistence.",
|
|
224
|
-
severity: "high",
|
|
225
|
-
stages: [
|
|
226
|
-
{
|
|
227
|
-
action: "file_read",
|
|
228
|
-
patterns: [
|
|
229
|
-
/\.bashrc/gi,
|
|
230
|
-
/\.zshrc/gi,
|
|
231
|
-
/\.profile/gi,
|
|
232
|
-
/crontab/gi,
|
|
233
|
-
/startup/gi,
|
|
234
|
-
/autostart/gi,
|
|
235
|
-
],
|
|
236
|
-
description: "Startup file access",
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
action: "persistence",
|
|
240
|
-
patterns: [/writeFile/gi, /appendFile/gi, /fs\.promises\.writeFile/gi],
|
|
241
|
-
description: "File modification",
|
|
242
|
-
},
|
|
243
|
-
],
|
|
244
|
-
legitimateUses: ["Shell configuration tools", "Development environment setup"],
|
|
245
|
-
redFlags: ["Writes to startup files", "Adds hidden entries", "No user interaction"],
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
id: "BEHAVIOR_SELF_PROPAGATION",
|
|
249
|
-
title: "Self-propagation pattern",
|
|
250
|
-
description: "Code accesses package publishing credentials and attempts to publish itself. This is worm-like behavior.",
|
|
251
|
-
severity: "critical",
|
|
252
|
-
stages: [
|
|
253
|
-
{
|
|
254
|
-
action: "file_read",
|
|
255
|
-
patterns: [/\.npmrc/gi, /NPM_TOKEN/gi, /OPENVSX_TOKEN/gi, /npm\s+config/gi],
|
|
256
|
-
description: "Publishing credential access",
|
|
257
|
-
},
|
|
258
|
-
{
|
|
259
|
-
action: "exec",
|
|
260
|
-
patterns: [/npm\s+publish/gi, /vsce\s+publish/gi, /ovsx\s+publish/gi, /yarn\s+publish/gi],
|
|
261
|
-
description: "Package publishing",
|
|
262
|
-
},
|
|
263
|
-
],
|
|
264
|
-
redFlags: ["Accesses publish tokens", "Runs publish commands", "GlassWorm-style worm"],
|
|
265
|
-
},
|
|
266
|
-
];
|
|
267
|
-
/**
|
|
268
|
-
* Find all matches for patterns in content
|
|
269
|
-
*/
|
|
270
|
-
function findPatternMatches(content, patterns) {
|
|
271
|
-
const matches = [];
|
|
272
|
-
for (const pattern of patterns) {
|
|
273
|
-
const regex = new RegExp(pattern.source, pattern.flags);
|
|
274
|
-
let match;
|
|
275
|
-
while ((match = regex.exec(content)) !== null) {
|
|
276
|
-
matches.push({
|
|
277
|
-
index: match.index,
|
|
278
|
-
matched: match[0].slice(0, 60),
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
return matches;
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Check if a signature matches in the content
|
|
286
|
-
*/
|
|
287
|
-
function checkSignature(content, signature) {
|
|
288
|
-
const stageMatches = [];
|
|
289
|
-
const minStages = signature.minStages ?? signature.stages.length;
|
|
290
|
-
const maxSpan = signature.maxSpan ?? 3000;
|
|
291
|
-
// Find matches for each stage
|
|
292
|
-
for (const stage of signature.stages) {
|
|
293
|
-
const matches = findPatternMatches(content, stage.patterns);
|
|
294
|
-
if (matches.length > 0) {
|
|
295
|
-
const firstMatch = matches[0];
|
|
296
|
-
if (firstMatch) {
|
|
297
|
-
stageMatches.push({
|
|
298
|
-
stage,
|
|
299
|
-
index: firstMatch.index,
|
|
300
|
-
matched: firstMatch.matched,
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
// Check if enough stages matched
|
|
306
|
-
if (stageMatches.length < minStages) {
|
|
307
|
-
return null;
|
|
308
|
-
}
|
|
309
|
-
// Check if stages are within maxSpan
|
|
310
|
-
if (stageMatches.length > 1) {
|
|
311
|
-
const indices = stageMatches.map((m) => m.index);
|
|
312
|
-
const span = Math.max(...indices) - Math.min(...indices);
|
|
313
|
-
if (span > maxSpan) {
|
|
314
|
-
return null;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
return stageMatches;
|
|
318
|
-
}
|
|
319
|
-
export function checkBehavioral(contents) {
|
|
320
|
-
const findings = [];
|
|
321
|
-
const seenFindings = new Set();
|
|
322
|
-
for (const [filename, buffer] of contents.files) {
|
|
323
|
-
if (!isScannable(filename, SCANNABLE_EXTENSIONS_PATTERN))
|
|
324
|
-
continue;
|
|
325
|
-
const content = buffer.toString("utf8");
|
|
326
|
-
for (const signature of SIGNATURES) {
|
|
327
|
-
const stageMatches = checkSignature(content, signature);
|
|
328
|
-
if (!stageMatches)
|
|
329
|
-
continue;
|
|
330
|
-
// Deduplicate
|
|
331
|
-
const key = `${signature.id}:${filename}`;
|
|
332
|
-
if (seenFindings.has(key))
|
|
333
|
-
continue;
|
|
334
|
-
seenFindings.add(key);
|
|
335
|
-
const firstMatch = stageMatches[0];
|
|
336
|
-
if (!firstMatch)
|
|
337
|
-
continue;
|
|
338
|
-
findings.push({
|
|
339
|
-
id: signature.id,
|
|
340
|
-
title: signature.title,
|
|
341
|
-
description: signature.description,
|
|
342
|
-
severity: signature.severity,
|
|
343
|
-
category: "behavioral",
|
|
344
|
-
location: {
|
|
345
|
-
file: filename,
|
|
346
|
-
line: findLineNumberByIndex(content, firstMatch.index),
|
|
347
|
-
},
|
|
348
|
-
metadata: {
|
|
349
|
-
stagesMatched: stageMatches.length,
|
|
350
|
-
totalStages: signature.stages.length,
|
|
351
|
-
stages: stageMatches.map((m) => ({
|
|
352
|
-
action: m.stage.action,
|
|
353
|
-
description: m.stage.description,
|
|
354
|
-
matched: m.matched,
|
|
355
|
-
line: findLineNumberByIndex(content, m.index),
|
|
356
|
-
})),
|
|
357
|
-
...(signature.legitimateUses && {
|
|
358
|
-
legitimateUses: signature.legitimateUses,
|
|
359
|
-
}),
|
|
360
|
-
...(signature.redFlags && { redFlags: signature.redFlags }),
|
|
361
|
-
},
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
return findings;
|
|
366
|
-
}
|
|
367
|
-
//# sourceMappingURL=behavioral.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"behavioral.js","sourceRoot":"","sources":["../../../src/scanner/checks/behavioral.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blocklist.d.ts","sourceRoot":"","sources":["../../../src/scanner/checks/blocklist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAUzE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,EAAE,CAyB7F"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
function matchesWildcard(extensionId, pattern) {
|
|
2
|
-
if (pattern.endsWith(".*")) {
|
|
3
|
-
const prefix = pattern.slice(0, -2);
|
|
4
|
-
return extensionId.startsWith(prefix + ".");
|
|
5
|
-
}
|
|
6
|
-
return extensionId === pattern;
|
|
7
|
-
}
|
|
8
|
-
export function checkBlocklist(manifest, blocklist) {
|
|
9
|
-
const findings = [];
|
|
10
|
-
const extensionId = `${manifest.publisher}.${manifest.name}`;
|
|
11
|
-
for (const entry of blocklist) {
|
|
12
|
-
if (matchesWildcard(extensionId, entry.id)) {
|
|
13
|
-
findings.push({
|
|
14
|
-
id: "BLOCKLIST_MATCH",
|
|
15
|
-
title: "Extension on malware blocklist",
|
|
16
|
-
description: `Extension "${extensionId}" matches blocklisted pattern "${entry.id}": ${entry.reason}`,
|
|
17
|
-
severity: "critical",
|
|
18
|
-
category: "blocklist",
|
|
19
|
-
location: {
|
|
20
|
-
file: "package.json",
|
|
21
|
-
},
|
|
22
|
-
metadata: {
|
|
23
|
-
campaign: entry.campaign,
|
|
24
|
-
reference: entry.reference,
|
|
25
|
-
blocklistEntry: entry.id,
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return findings;
|
|
31
|
-
}
|
|
32
|
-
//# sourceMappingURL=blocklist.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blocklist.js","sourceRoot":"","sources":["../../../src/scanner/checks/blocklist.ts"],"names":[],"mappings":"AAEA,SAAS,eAAe,CAAC,WAAmB,EAAE,OAAe;IAC3D,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACpC,OAAO,WAAW,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,WAAW,KAAK,OAAO,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAsB,EAAE,SAA2B;IAChF,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,GAAG,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;IAE7D,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC9B,IAAI,eAAe,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;YAC3C,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,iBAAiB;gBACrB,KAAK,EAAE,gCAAgC;gBACvC,WAAW,EAAE,cAAc,WAAW,kCAAkC,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC,MAAM,EAAE;gBACpG,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,WAAW;gBACrB,QAAQ,EAAE;oBACR,IAAI,EAAE,cAAc;iBACrB;gBACD,QAAQ,EAAE;oBACR,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,SAAS,EAAE,KAAK,CAAC,SAAS;oBAC1B,cAAc,EAAE,KAAK,CAAC,EAAE;iBACzB;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blocklist.test.d.ts","sourceRoot":"","sources":["../../../src/scanner/checks/blocklist.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { checkBlocklist } from "./blocklist.js";
|
|
3
|
-
describe("checkBlocklist", () => {
|
|
4
|
-
const blocklist = [
|
|
5
|
-
{
|
|
6
|
-
id: "malicious.extension",
|
|
7
|
-
name: "Malicious Extension",
|
|
8
|
-
reason: "Known malware",
|
|
9
|
-
campaign: "Test",
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
id: "badpublisher.*",
|
|
13
|
-
name: "Bad Publisher (all)",
|
|
14
|
-
reason: "All extensions from this publisher are malicious",
|
|
15
|
-
campaign: "Test",
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
id: "498-00.*",
|
|
19
|
-
name: "498-00 publisher (all)",
|
|
20
|
-
reason: "TigerJack republished extensions",
|
|
21
|
-
campaign: "TigerJack",
|
|
22
|
-
},
|
|
23
|
-
];
|
|
24
|
-
it("matches exact extension ID", () => {
|
|
25
|
-
const manifest = {
|
|
26
|
-
name: "extension",
|
|
27
|
-
publisher: "malicious",
|
|
28
|
-
version: "1.0.0",
|
|
29
|
-
};
|
|
30
|
-
const findings = checkBlocklist(manifest, blocklist);
|
|
31
|
-
expect(findings).toHaveLength(1);
|
|
32
|
-
expect(findings[0]?.id).toBe("BLOCKLIST_MATCH");
|
|
33
|
-
expect(findings[0]?.severity).toBe("critical");
|
|
34
|
-
});
|
|
35
|
-
it("matches wildcard publisher pattern", () => {
|
|
36
|
-
const manifest = {
|
|
37
|
-
name: "some-extension",
|
|
38
|
-
publisher: "badpublisher",
|
|
39
|
-
version: "1.0.0",
|
|
40
|
-
};
|
|
41
|
-
const findings = checkBlocklist(manifest, blocklist);
|
|
42
|
-
expect(findings).toHaveLength(1);
|
|
43
|
-
expect(findings[0]?.metadata?.["blocklistEntry"]).toBe("badpublisher.*");
|
|
44
|
-
});
|
|
45
|
-
it("matches publisher with special characters in pattern", () => {
|
|
46
|
-
const manifest = {
|
|
47
|
-
name: "pythonformat",
|
|
48
|
-
publisher: "498-00",
|
|
49
|
-
version: "1.0.0",
|
|
50
|
-
};
|
|
51
|
-
const findings = checkBlocklist(manifest, blocklist);
|
|
52
|
-
expect(findings).toHaveLength(1);
|
|
53
|
-
expect(findings[0]?.metadata?.["blocklistEntry"]).toBe("498-00.*");
|
|
54
|
-
});
|
|
55
|
-
it("does not match clean extension", () => {
|
|
56
|
-
const manifest = {
|
|
57
|
-
name: "clean-extension",
|
|
58
|
-
publisher: "trusted-publisher",
|
|
59
|
-
version: "1.0.0",
|
|
60
|
-
};
|
|
61
|
-
const findings = checkBlocklist(manifest, blocklist);
|
|
62
|
-
expect(findings).toHaveLength(0);
|
|
63
|
-
});
|
|
64
|
-
it("does not match partial ID without wildcard", () => {
|
|
65
|
-
const manifest = {
|
|
66
|
-
name: "extension-extra",
|
|
67
|
-
publisher: "malicious",
|
|
68
|
-
version: "1.0.0",
|
|
69
|
-
};
|
|
70
|
-
const findings = checkBlocklist(manifest, blocklist);
|
|
71
|
-
expect(findings).toHaveLength(0);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
//# sourceMappingURL=blocklist.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blocklist.test.js","sourceRoot":"","sources":["../../../src/scanner/checks/blocklist.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { Finding, Severity, VsixContents } from "../types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Unified chain detection for multi-stage attack patterns.
|
|
4
|
-
*
|
|
5
|
-
* This module consolidates DataFlow (2-stage source→sink) and Behavioral (N-stage)
|
|
6
|
-
* detection into a single framework. Both share the same mechanics:
|
|
7
|
-
* - Find pattern matches across stages
|
|
8
|
-
* - Check proximity/span constraints
|
|
9
|
-
* - Deduplicate findings
|
|
10
|
-
*/
|
|
11
|
-
export interface ChainStage {
|
|
12
|
-
id: string;
|
|
13
|
-
name: string;
|
|
14
|
-
patterns: RegExp[];
|
|
15
|
-
}
|
|
16
|
-
export interface ChainRule {
|
|
17
|
-
id: string;
|
|
18
|
-
title: string;
|
|
19
|
-
description: string;
|
|
20
|
-
severity: Severity;
|
|
21
|
-
stages: ChainStage[];
|
|
22
|
-
constraints: {
|
|
23
|
-
/** Minimum stages that must match (default: all) */
|
|
24
|
-
minStages?: number;
|
|
25
|
-
/** Maximum distance between first and last stage match (default: 3000 chars) */
|
|
26
|
-
maxSpan?: number;
|
|
27
|
-
};
|
|
28
|
-
legitimateUses?: string[];
|
|
29
|
-
redFlags?: string[];
|
|
30
|
-
}
|
|
31
|
-
declare const STAGES: Record<string, ChainStage>;
|
|
32
|
-
declare const CHAIN_RULES: ChainRule[];
|
|
33
|
-
export declare function checkChains(contents: VsixContents): Finding[];
|
|
34
|
-
export { CHAIN_RULES, STAGES };
|
|
35
|
-
//# sourceMappingURL=chains.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../../../src/scanner/checks/chains.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGnE;;;;;;;;GAQG;AAEH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,WAAW,EAAE;QACX,oDAAoD;QACpD,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gFAAgF;QAChF,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAaD,QAAA,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAgOtC,CAAC;AAMF,QAAA,MAAM,WAAW,EAAE,SAAS,EA6K3B,CAAC;AAyEF,wBAAgB,WAAW,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,EAAE,CAmD7D;AAGD,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC"}
|