@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.
Files changed (58) hide show
  1. package/dist/index.js +0 -0
  2. package/package.json +1 -1
  3. package/dist/scanner/checks/behavioral.d.ts +0 -3
  4. package/dist/scanner/checks/behavioral.d.ts.map +0 -1
  5. package/dist/scanner/checks/behavioral.js +0 -367
  6. package/dist/scanner/checks/behavioral.js.map +0 -1
  7. package/dist/scanner/checks/blocklist.d.ts +0 -3
  8. package/dist/scanner/checks/blocklist.d.ts.map +0 -1
  9. package/dist/scanner/checks/blocklist.js +0 -32
  10. package/dist/scanner/checks/blocklist.js.map +0 -1
  11. package/dist/scanner/checks/blocklist.test.d.ts +0 -2
  12. package/dist/scanner/checks/blocklist.test.d.ts.map +0 -1
  13. package/dist/scanner/checks/blocklist.test.js +0 -74
  14. package/dist/scanner/checks/blocklist.test.js.map +0 -1
  15. package/dist/scanner/checks/chains.d.ts +0 -35
  16. package/dist/scanner/checks/chains.d.ts.map +0 -1
  17. package/dist/scanner/checks/chains.js +0 -505
  18. package/dist/scanner/checks/chains.js.map +0 -1
  19. package/dist/scanner/checks/chains.test.d.ts +0 -2
  20. package/dist/scanner/checks/chains.test.d.ts.map +0 -1
  21. package/dist/scanner/checks/chains.test.js +0 -250
  22. package/dist/scanner/checks/chains.test.js.map +0 -1
  23. package/dist/scanner/checks/dataflow.d.ts +0 -3
  24. package/dist/scanner/checks/dataflow.d.ts.map +0 -1
  25. package/dist/scanner/checks/dataflow.js +0 -316
  26. package/dist/scanner/checks/dataflow.js.map +0 -1
  27. package/dist/scanner/checks/dependencies.d.ts +0 -13
  28. package/dist/scanner/checks/dependencies.d.ts.map +0 -1
  29. package/dist/scanner/checks/dependencies.js +0 -225
  30. package/dist/scanner/checks/dependencies.js.map +0 -1
  31. package/dist/scanner/checks/dependencies.test.d.ts +0 -2
  32. package/dist/scanner/checks/dependencies.test.d.ts.map +0 -1
  33. package/dist/scanner/checks/dependencies.test.js +0 -248
  34. package/dist/scanner/checks/dependencies.test.js.map +0 -1
  35. package/dist/scanner/checks/manifest.d.ts +0 -6
  36. package/dist/scanner/checks/manifest.d.ts.map +0 -1
  37. package/dist/scanner/checks/manifest.js +0 -123
  38. package/dist/scanner/checks/manifest.js.map +0 -1
  39. package/dist/scanner/checks/manifest.test.d.ts +0 -2
  40. package/dist/scanner/checks/manifest.test.d.ts.map +0 -1
  41. package/dist/scanner/checks/manifest.test.js +0 -108
  42. package/dist/scanner/checks/manifest.test.js.map +0 -1
  43. package/dist/scanner/checks/patterns.d.ts +0 -5
  44. package/dist/scanner/checks/patterns.d.ts.map +0 -1
  45. package/dist/scanner/checks/patterns.js +0 -251
  46. package/dist/scanner/checks/patterns.js.map +0 -1
  47. package/dist/scanner/checks/patterns.test.d.ts +0 -2
  48. package/dist/scanner/checks/patterns.test.d.ts.map +0 -1
  49. package/dist/scanner/checks/patterns.test.js +0 -147
  50. package/dist/scanner/checks/patterns.test.js.map +0 -1
  51. package/dist/scanner/checks/unicode.d.ts +0 -3
  52. package/dist/scanner/checks/unicode.d.ts.map +0 -1
  53. package/dist/scanner/checks/unicode.js +0 -247
  54. package/dist/scanner/checks/unicode.js.map +0 -1
  55. package/dist/scanner/checks/unicode.test.d.ts +0 -2
  56. package/dist/scanner/checks/unicode.test.d.ts.map +0 -1
  57. package/dist/scanner/checks/unicode.test.js +0 -202
  58. package/dist/scanner/checks/unicode.test.js.map +0 -1
package/dist/index.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trailofbits/vsix-audit",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Security scanner for VS Code extensions",
5
5
  "keywords": [
6
6
  "audit",
@@ -1,3 +0,0 @@
1
- import type { Finding, VsixContents } from "../types.js";
2
- export declare function checkBehavioral(contents: VsixContents): Finding[];
3
- //# sourceMappingURL=behavioral.d.ts.map
@@ -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,3 +0,0 @@
1
- import type { BlocklistEntry, Finding, VsixManifest } from "../types.js";
2
- export declare function checkBlocklist(manifest: VsixManifest, blocklist: BlocklistEntry[]): Finding[];
3
- //# sourceMappingURL=blocklist.d.ts.map
@@ -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,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=blocklist.test.d.ts.map
@@ -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"}