@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,432 @@
1
+ import { detectBundler } from "../bundler.js";
2
+ import { isScannable, SCANNABLE_EXTENSIONS_PATTERN, SCANNABLE_EXTENSIONS_UNICODE, } from "../constants.js";
3
+ import { findLineNumberByIndex } from "../utils.js";
4
+ // ============================================================================
5
+ // SHARED UTILITIES
6
+ // ============================================================================
7
+ /**
8
+ * Check if file is in node_modules (third-party dependencies).
9
+ * These are not extension code and generate many false positives.
10
+ */
11
+ function isNodeModules(filename) {
12
+ return filename.includes("node_modules/") || filename.includes("node_modules\\");
13
+ }
14
+ // ============================================================================
15
+ // ENTROPY ANALYSIS
16
+ // ============================================================================
17
+ /**
18
+ * Calculate Shannon entropy of a string.
19
+ * Higher entropy indicates more randomness, often a sign of obfuscation.
20
+ * Normal code: ~4.5 bits/char, obfuscated: >5.5
21
+ */
22
+ function shannonEntropy(str) {
23
+ if (str.length === 0)
24
+ return 0;
25
+ const freq = {};
26
+ for (const char of str) {
27
+ freq[char] = (freq[char] ?? 0) + 1;
28
+ }
29
+ let entropy = 0;
30
+ const len = str.length;
31
+ for (const count of Object.values(freq)) {
32
+ const p = count / len;
33
+ entropy -= p * Math.log2(p);
34
+ }
35
+ return entropy;
36
+ }
37
+ /**
38
+ * Find high-entropy regions in code (potential obfuscation).
39
+ * Uses a sliding window approach.
40
+ */
41
+ function findHighEntropyRegions(content, windowSize = 200, threshold = 5.5) {
42
+ const regions = [];
43
+ const step = 50;
44
+ for (let i = 0; i < content.length - windowSize; i += step) {
45
+ const window = content.slice(i, i + windowSize);
46
+ // Skip whitespace-heavy regions
47
+ const nonWhitespace = window.replace(/\s/g, "");
48
+ if (nonWhitespace.length < windowSize * 0.3)
49
+ continue;
50
+ const entropy = shannonEntropy(nonWhitespace);
51
+ if (entropy > threshold) {
52
+ // Merge with previous region if overlapping
53
+ const last = regions.at(-1);
54
+ if (last && i < last.end + step) {
55
+ last.end = i + windowSize;
56
+ last.entropy = Math.max(last.entropy, entropy);
57
+ }
58
+ else {
59
+ regions.push({ start: i, end: i + windowSize, entropy });
60
+ }
61
+ }
62
+ }
63
+ return regions;
64
+ }
65
+ function checkEntropy(contents) {
66
+ const findings = [];
67
+ const seenFindings = new Set();
68
+ for (const [filename, buffer] of contents.files) {
69
+ if (!isScannable(filename, SCANNABLE_EXTENSIONS_PATTERN))
70
+ continue;
71
+ // Skip node_modules - third-party deps generate many false positives
72
+ if (isNodeModules(filename))
73
+ continue;
74
+ const content = buffer.toString("utf8");
75
+ // Skip bundled code - minification naturally increases entropy
76
+ const bundlerInfo = detectBundler(content, filename);
77
+ if (bundlerInfo.isBundled)
78
+ continue;
79
+ const regions = findHighEntropyRegions(content);
80
+ if (regions.length === 0)
81
+ continue;
82
+ const key = `OBFUSCATION_HIGH_ENTROPY:${filename}`;
83
+ if (seenFindings.has(key))
84
+ continue;
85
+ seenFindings.add(key);
86
+ const firstRegion = regions[0];
87
+ if (!firstRegion)
88
+ continue;
89
+ const matches = regions.map((region) => ({
90
+ index: region.start,
91
+ matched: `Entropy: ${region.entropy.toFixed(2)} bits/char`,
92
+ score: Math.min(90, Math.floor(region.entropy * 15)),
93
+ }));
94
+ findings.push({
95
+ id: "OBFUSCATION_HIGH_ENTROPY",
96
+ title: "High entropy code region",
97
+ description: "Code region has unusually high Shannon entropy (randomness). This often indicates obfuscated or encoded content.",
98
+ severity: "medium",
99
+ category: "obfuscation",
100
+ location: {
101
+ file: filename,
102
+ line: findLineNumberByIndex(content, firstRegion.start),
103
+ },
104
+ metadata: {
105
+ matchCount: matches.length,
106
+ matched: matches[0]?.matched,
107
+ obfuscationScore: Math.max(...matches.map((m) => m.score)),
108
+ legitimateUses: ["Compressed data", "Base64 content", "Hash strings"],
109
+ redFlags: ["Near eval/Function", "Large continuous regions"],
110
+ },
111
+ });
112
+ }
113
+ return findings;
114
+ }
115
+ // ============================================================================
116
+ // UNICODE HIDING DETECTION
117
+ // ============================================================================
118
+ function findLineAndColumn(content, index) {
119
+ const beforeMatch = content.slice(0, index);
120
+ const lines = beforeMatch.split("\n");
121
+ const line = lines.length;
122
+ const column = (lines.at(-1)?.length ?? 0) + 1;
123
+ return { line, column };
124
+ }
125
+ function getContext(content, index, length) {
126
+ const start = Math.max(0, index - 20);
127
+ const end = Math.min(content.length, index + length + 20);
128
+ let ctx = content.slice(start, end);
129
+ if (start > 0)
130
+ ctx = "..." + ctx;
131
+ if (end < content.length)
132
+ ctx = ctx + "...";
133
+ return ctx.replace(/[\n\r]/g, "\\n").slice(0, 80);
134
+ }
135
+ // Zero-width characters: U+200B-200D, U+FEFF
136
+ const ZERO_WIDTH_REGEX = /[\u200B-\u200D\uFEFF]/g;
137
+ // Variation selectors: U+FE00-FE0F (GlassWorm technique)
138
+ const VARIATION_SELECTOR_REGEX = /[\uFE00-\uFE0F]/g;
139
+ // Bidirectional overrides: U+202A-202E (Trojan Source attack)
140
+ const BIDI_OVERRIDE_REGEX = /[\u202A-\u202E]/g;
141
+ // Unicode escapes for ASCII: \u00XX where XX is 20-7E (printable ASCII)
142
+ const UNICODE_ASCII_ESCAPE_REGEX = /\\u00[2-7][0-9a-fA-F]/g;
143
+ // Cyrillic homoglyphs that look like Latin letters
144
+ const CYRILLIC_LOOKALIKE_REGEX = /[\u0430\u0441\u0435\u043E\u0440\u0445\u0443\u0410\u0412\u0421\u0415\u041D\u041A\u041C\u041E\u0420\u0422\u0425]/g;
145
+ // Additional invisible/confusable characters
146
+ const OTHER_INVISIBLE_REGEX = /[\u00AD\u034F\u115F\u1160\u17B4\u17B5\u180E\u2060-\u2064\u206A-\u206F]/g;
147
+ function detectUnicodePattern(content, regex, minMatches = 1) {
148
+ const matches = [];
149
+ const r = new RegExp(regex.source, regex.flags);
150
+ let match;
151
+ while ((match = r.exec(content)) !== null) {
152
+ const { line, column } = findLineAndColumn(content, match.index);
153
+ matches.push({
154
+ line,
155
+ column,
156
+ matched: match[0],
157
+ context: getContext(content, match.index, match[0].length),
158
+ });
159
+ }
160
+ return matches.length >= minMatches ? matches : [];
161
+ }
162
+ /**
163
+ * Check if the file appears to be primarily i18n/localization content.
164
+ */
165
+ function isI18nFile(filename, content) {
166
+ const i18nPatterns = [
167
+ /locales?\//i,
168
+ /i18n\//i,
169
+ /translations?\//i,
170
+ /lang\//i,
171
+ /messages/i,
172
+ /\.l10n\./i,
173
+ /nls\./i,
174
+ // moment locale files (e.g., moment/locale/ku.js)
175
+ /moment\/.*locale/i,
176
+ // Encoding tables (iconv-lite encodings/tables/*.js)
177
+ /encodings?\/(tables|sbcs)/i,
178
+ // HTML entities data
179
+ /entities\.json$/i,
180
+ // Emoji data files
181
+ /emoji\.json$/i,
182
+ // CLI spinners data
183
+ /spinners\.json$/i,
184
+ // Public Suffix List
185
+ /psl\//i,
186
+ // VS Code NLS localization files (package.nls.*.json)
187
+ /package\.nls\.[a-z]{2}(-[a-z]{2})?\.json$/i,
188
+ ];
189
+ if (i18nPatterns.some((p) => p.test(filename))) {
190
+ return true;
191
+ }
192
+ if (filename.endsWith(".json")) {
193
+ const keyValuePairs = (content.match(/"[^"]+"\s*:\s*"[^"]+"/g) ?? []).length;
194
+ const lines = content.split("\n").length;
195
+ if (keyValuePairs / lines > 0.5 && keyValuePairs > 10) {
196
+ return true;
197
+ }
198
+ }
199
+ // Persian (Farsi) and Arabic scripts use zero-width non-joiner (U+200C) legitimately
200
+ // for proper text rendering. Detect these scripts by their Unicode ranges.
201
+ const hasPersianArabicScript = /[\u0600-\u06FF\u0750-\u077F]/.test(content);
202
+ if (hasPersianArabicScript && filename.endsWith(".json")) {
203
+ return true;
204
+ }
205
+ return false;
206
+ }
207
+ /**
208
+ * Check if file has legitimate RTL text support (math, diagrams, language files).
209
+ */
210
+ function isRtlFile(filename) {
211
+ const rtlPatterns = [
212
+ /katex/i, // KaTeX math rendering
213
+ /mermaid/i, // Mermaid diagram library
214
+ /mathjax/i, // MathJax math rendering
215
+ /drawio.*\/(dia_he|dia_fa|dia_ar)/i, // DrawIO Hebrew/Farsi/Arabic language files
216
+ /_he\.txt$/i, // Hebrew language files
217
+ /_fa\.txt$/i, // Farsi language files
218
+ /_ar\.txt$/i, // Arabic language files
219
+ ];
220
+ return rtlPatterns.some((p) => p.test(filename));
221
+ }
222
+ /**
223
+ * Check if invisible characters are in proximity to execution patterns.
224
+ */
225
+ function hasExecutionInProximity(content, invisibleIndex, proximityChars = 200) {
226
+ const start = Math.max(0, invisibleIndex - proximityChars);
227
+ const end = Math.min(content.length, invisibleIndex + proximityChars);
228
+ const region = content.slice(start, end);
229
+ const execPatterns = [
230
+ /eval\s*\(/i,
231
+ /Function\s*\(/i,
232
+ /exec\s*\(/i,
233
+ /spawn\s*\(/i,
234
+ /execSync\s*\(/i,
235
+ /child_process/i,
236
+ /\.\s*call\s*\(/,
237
+ /\.\s*apply\s*\(/,
238
+ /new\s+Function/i,
239
+ /atob\s*\(/i,
240
+ /Buffer\.from/i,
241
+ ];
242
+ return execPatterns.some((p) => p.test(region));
243
+ }
244
+ // Rules that should be skipped for bundled code and node_modules
245
+ const SKIP_UNICODE_FOR_BUNDLED = new Set([
246
+ "ZERO_WIDTH_CHARS",
247
+ "CYRILLIC_HOMOGLYPH",
248
+ "OTHER_INVISIBLE_CHARS",
249
+ "UNICODE_ASCII_ESCAPE",
250
+ ]);
251
+ // Rules that should be skipped for node_modules (third-party deps)
252
+ // Critical rules (VARIATION_SELECTOR, BIDI_OVERRIDE, INVISIBLE_CODE_EXECUTION) still run
253
+ const SKIP_UNICODE_FOR_NODE_MODULES = new Set([
254
+ "ZERO_WIDTH_CHARS",
255
+ "CYRILLIC_HOMOGLYPH",
256
+ "OTHER_INVISIBLE_CHARS",
257
+ "UNICODE_ASCII_ESCAPE",
258
+ "OBFUSCATION_HIGH_ENTROPY",
259
+ ]);
260
+ const UNICODE_RULES = [
261
+ {
262
+ id: "ZERO_WIDTH_CHARS",
263
+ title: "Zero-width characters detected",
264
+ description: "File contains zero-width Unicode characters (U+200B-200D, U+FEFF). These invisible characters can hide malicious code or be used for steganography.",
265
+ severity: "high",
266
+ detect: (content, filename) => {
267
+ // Skip i18n files - Persian, Arabic, Kurdish etc. use U+200C (ZWNJ) legitimately
268
+ if (isI18nFile(filename, content))
269
+ return [];
270
+ return detectUnicodePattern(content, ZERO_WIDTH_REGEX, 3);
271
+ },
272
+ },
273
+ {
274
+ id: "VARIATION_SELECTOR",
275
+ title: "Unicode variation selectors detected (GlassWorm technique)",
276
+ description: "File contains many Unicode variation selectors (U+FE00-FE0F). GlassWorm malware uses these to hide executable code.",
277
+ severity: "critical",
278
+ detect: (content, filename) => {
279
+ // Skip emoji/entity data files that legitimately use variation selectors
280
+ const emojiDataPatterns = [
281
+ /emoji/i,
282
+ /entities/i,
283
+ /spinners/i,
284
+ /\.md$/i, // README files often have emoji
285
+ /gemoji/i, // GitHub emoji library
286
+ /twemoji/i, // Twitter emoji
287
+ /node-emoji/i, // node-emoji package
288
+ /unicode.*data/i, // Unicode data files
289
+ /emojis?\.(json|js|ts)$/i, // emoji data files
290
+ ];
291
+ if (emojiDataPatterns.some((p) => p.test(filename)))
292
+ return [];
293
+ // If file contains many actual emoji characters, it's likely legitimate emoji data
294
+ // Emoji ranges: Emoticons, Dingbats, Symbols, Flags, etc.
295
+ // eslint-disable-next-line no-misleading-character-class
296
+ const emojiPattern = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/gu;
297
+ const emojiMatches = content.match(emojiPattern);
298
+ if (emojiMatches && emojiMatches.length > 100)
299
+ return [];
300
+ // GlassWorm uses hundreds of variation selectors; 50 is well above normal emoji use
301
+ return detectUnicodePattern(content, VARIATION_SELECTOR_REGEX, 50);
302
+ },
303
+ },
304
+ {
305
+ id: "BIDI_OVERRIDE",
306
+ title: "Bidirectional text override detected (Trojan Source)",
307
+ description: "File contains Unicode bidirectional override characters (U+202A-202E). This is the Trojan Source attack technique.",
308
+ severity: "critical",
309
+ detect: (content, filename) => {
310
+ // Skip files with legitimate RTL text support (math, diagrams, language files)
311
+ if (isRtlFile(filename))
312
+ return [];
313
+ return detectUnicodePattern(content, BIDI_OVERRIDE_REGEX, 1);
314
+ },
315
+ },
316
+ {
317
+ id: "UNICODE_ASCII_ESCAPE",
318
+ title: "Unicode escape sequences for ASCII characters",
319
+ description: "File uses Unicode escape sequences (\\u00XX) for normal ASCII characters. This is a common obfuscation technique.",
320
+ severity: "medium",
321
+ detect: (content) => detectUnicodePattern(content, UNICODE_ASCII_ESCAPE_REGEX, 5),
322
+ },
323
+ {
324
+ id: "CYRILLIC_HOMOGLYPH",
325
+ title: "Cyrillic homoglyph characters detected",
326
+ description: "File contains Cyrillic characters that visually resemble Latin letters. This can be used for homoglyph attacks.",
327
+ severity: "high",
328
+ detect: (content, filename) => {
329
+ if (filename.endsWith(".md") || filename.endsWith(".txt")) {
330
+ return [];
331
+ }
332
+ if (isI18nFile(filename, content)) {
333
+ return [];
334
+ }
335
+ return detectUnicodePattern(content, CYRILLIC_LOOKALIKE_REGEX, 1);
336
+ },
337
+ },
338
+ {
339
+ id: "OTHER_INVISIBLE_CHARS",
340
+ title: "Other invisible Unicode characters detected",
341
+ description: "File contains invisible Unicode characters (soft hyphens, combining marks, format controls).",
342
+ severity: "medium",
343
+ detect: (content) => detectUnicodePattern(content, OTHER_INVISIBLE_REGEX, 3),
344
+ },
345
+ {
346
+ id: "INVISIBLE_CODE_EXECUTION",
347
+ title: "Invisible characters near code execution",
348
+ description: "File contains many invisible Unicode characters in proximity to code execution functions. Strong indicator of hidden malicious code.",
349
+ severity: "critical",
350
+ detect: (content, filename) => {
351
+ if (isI18nFile(filename, content)) {
352
+ return [];
353
+ }
354
+ const suspiciousInvisible = new RegExp(`${VARIATION_SELECTOR_REGEX.source}|${BIDI_OVERRIDE_REGEX.source}`, "g");
355
+ const matches = detectUnicodePattern(content, suspiciousInvisible, 5);
356
+ return matches.filter((m) => {
357
+ const matchIndex = content.slice(0, m.line).split("\n").length > 1
358
+ ? content
359
+ .split("\n")
360
+ .slice(0, m.line - 1)
361
+ .join("\n").length + m.column
362
+ : m.column;
363
+ return hasExecutionInProximity(content, matchIndex);
364
+ });
365
+ },
366
+ },
367
+ ];
368
+ function checkUnicodeHiding(contents) {
369
+ const findings = [];
370
+ const seenFindings = new Set();
371
+ for (const [filename, buffer] of contents.files) {
372
+ if (!isScannable(filename, SCANNABLE_EXTENSIONS_UNICODE))
373
+ continue;
374
+ const content = buffer.toString("utf8");
375
+ const bundlerInfo = detectBundler(content, filename);
376
+ const inNodeModules = isNodeModules(filename);
377
+ for (const rule of UNICODE_RULES) {
378
+ // Skip non-critical rules for bundled code
379
+ if (bundlerInfo.isBundled && SKIP_UNICODE_FOR_BUNDLED.has(rule.id)) {
380
+ continue;
381
+ }
382
+ // Skip non-critical rules for node_modules (third-party deps)
383
+ if (inNodeModules && SKIP_UNICODE_FOR_NODE_MODULES.has(rule.id)) {
384
+ continue;
385
+ }
386
+ const matches = rule.detect(content, filename);
387
+ if (matches.length === 0)
388
+ continue;
389
+ const key = `${rule.id}:${filename}`;
390
+ if (seenFindings.has(key))
391
+ continue;
392
+ seenFindings.add(key);
393
+ const firstMatch = matches[0];
394
+ if (!firstMatch)
395
+ continue;
396
+ findings.push({
397
+ id: rule.id,
398
+ title: rule.title,
399
+ description: rule.description,
400
+ severity: rule.severity,
401
+ category: "obfuscation",
402
+ location: {
403
+ file: filename,
404
+ line: firstMatch.line,
405
+ column: firstMatch.column,
406
+ },
407
+ metadata: {
408
+ matchCount: matches.length,
409
+ firstMatch: firstMatch.context,
410
+ codePoints: matches
411
+ .slice(0, 5)
412
+ .map((m) => [...m.matched]
413
+ .map((c) => `U+${c.codePointAt(0)?.toString(16).toUpperCase().padStart(4, "0")}`)
414
+ .join(", ")),
415
+ },
416
+ });
417
+ }
418
+ }
419
+ return findings;
420
+ }
421
+ // ============================================================================
422
+ // MAIN EXPORT
423
+ // ============================================================================
424
+ export function checkObfuscation(contents) {
425
+ const findings = [];
426
+ // Check entropy in code files (1 rule - YARA can't calculate entropy)
427
+ findings.push(...checkEntropy(contents));
428
+ // Check Unicode hiding in all text files (7 rules)
429
+ findings.push(...checkUnicodeHiding(contents));
430
+ return findings;
431
+ }
432
+ //# sourceMappingURL=obfuscation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obfuscation.js","sourceRoot":"","sources":["../../../src/scanner/checks/obfuscation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EACL,WAAW,EACX,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAoCpD,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;;GAGG;AACH,SAAS,aAAa,CAAC,QAAgB;IACrC,OAAO,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACnF,CAAC;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;;;GAIG;AACH,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAE/B,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC;IACvB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,KAAK,GAAG,GAAG,CAAC;QACtB,OAAO,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,SAAS,sBAAsB,CAC7B,OAAe,EACf,UAAU,GAAG,GAAG,EAChB,SAAS,GAAG,GAAG;IAEf,MAAM,OAAO,GAAsD,EAAE,CAAC;IACtE,MAAM,IAAI,GAAG,EAAE,CAAC;IAEhB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC;QAEhD,gCAAgC;QAChC,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAChD,IAAI,aAAa,CAAC,MAAM,GAAG,UAAU,GAAG,GAAG;YAAE,SAAS;QAEtD,MAAM,OAAO,GAAG,cAAc,CAAC,aAAa,CAAC,CAAC;QAC9C,IAAI,OAAO,GAAG,SAAS,EAAE,CAAC;YACxB,4CAA4C;YAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC;gBAChC,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC;gBAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACjD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,QAAsB;IAC1C,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAEvC,KAAK,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAChD,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,4BAA4B,CAAC;YAAE,SAAS;QACnE,qEAAqE;QACrE,IAAI,aAAa,CAAC,QAAQ,CAAC;YAAE,SAAS;QAEtC,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAExC,+DAA+D;QAC/D,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACrD,IAAI,WAAW,CAAC,SAAS;YAAE,SAAS;QAEpC,MAAM,OAAO,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEnC,MAAM,GAAG,GAAG,4BAA4B,QAAQ,EAAE,CAAC;QACnD,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QACpC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEtB,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAI,CAAC,WAAW;YAAE,SAAS;QAE3B,MAAM,OAAO,GAAmB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACvD,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,YAAY,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY;YAC1D,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;SACrD,CAAC,CAAC,CAAC;QAEJ,QAAQ,CAAC,IAAI,CAAC;YACZ,EAAE,EAAE,0BAA0B;YAC9B,KAAK,EAAE,0BAA0B;YACjC,WAAW,EACT,kHAAkH;YACpH,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,aAAa;YACvB,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,qBAAqB,CAAC,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC;aACxD;YACD,QAAQ,EAAE;gBACR,UAAU,EAAE,OAAO,CAAC,MAAM;gBAC1B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO;gBAC5B,gBAAgB,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBAC1D,cAAc,EAAE,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,CAAC;gBACrE,QAAQ,EAAE,CAAC,oBAAoB,EAAE,0BAA0B,CAAC;aAC7D;SACF,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,+EAA+E;AAC/E,2BAA2B;AAC3B,+EAA+E;AAE/E,SAAS,iBAAiB,CAAC,OAAe,EAAE,KAAa;IACvD,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC;IAC1B,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC;AAED,SAAS,UAAU,CAAC,OAAe,EAAE,KAAa,EAAE,MAAc;IAChE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,EAAE,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC;IAC1D,IAAI,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACpC,IAAI,KAAK,GAAG,CAAC;QAAE,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC;IACjC,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM;QAAE,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC;IAC5C,OAAO,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,6CAA6C;AAC7C,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AAElD,yDAAyD;AACzD,MAAM,wBAAwB,GAAG,kBAAkB,CAAC;AAEpD,8DAA8D;AAC9D,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AAE/C,wEAAwE;AACxE,MAAM,0BAA0B,GAAG,wBAAwB,CAAC;AAE5D,mDAAmD;AACnD,MAAM,wBAAwB,GAC5B,iHAAiH,CAAC;AAEpH,6CAA6C;AAC7C,MAAM,qBAAqB,GACzB,yEAAyE,CAAC;AAE5E,SAAS,oBAAoB,CAAC,OAAe,EAAE,KAAa,EAAE,UAAU,GAAG,CAAC;IAC1E,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,KAA6B,CAAC;IAElC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC1C,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC;YACX,IAAI;YACJ,MAAM;YACN,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YACjB,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;SAC3D,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,IAAI,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,QAAgB,EAAE,OAAe;IACnD,MAAM,YAAY,GAAG;QACnB,aAAa;QACb,SAAS;QACT,kBAAkB;QAClB,SAAS;QACT,WAAW;QACX,WAAW;QACX,QAAQ;QACR,kDAAkD;QAClD,mBAAmB;QACnB,qDAAqD;QACrD,4BAA4B;QAC5B,qBAAqB;QACrB,kBAAkB;QAClB,mBAAmB;QACnB,eAAe;QACf,oBAAoB;QACpB,kBAAkB;QAClB,qBAAqB;QACrB,QAAQ;QACR,sDAAsD;QACtD,4CAA4C;KAC7C,CAAC;IACF,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,MAAM,aAAa,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QAC7E,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;QACzC,IAAI,aAAa,GAAG,KAAK,GAAG,GAAG,IAAI,aAAa,GAAG,EAAE,EAAE,CAAC;YACtD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,qFAAqF;IACrF,2EAA2E;IAC3E,MAAM,sBAAsB,GAAG,8BAA8B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5E,IAAI,sBAAsB,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,QAAgB;IACjC,MAAM,WAAW,GAAG;QAClB,QAAQ,EAAE,uBAAuB;QACjC,UAAU,EAAE,0BAA0B;QACtC,UAAU,EAAE,yBAAyB;QACrC,mCAAmC,EAAE,4CAA4C;QACjF,YAAY,EAAE,wBAAwB;QACtC,YAAY,EAAE,uBAAuB;QACrC,YAAY,EAAE,wBAAwB;KACvC,CAAC;IACF,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAC9B,OAAe,EACf,cAAsB,EACtB,cAAc,GAAG,GAAG;IAEpB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,GAAG,cAAc,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEzC,MAAM,YAAY,GAAG;QACnB,YAAY;QACZ,gBAAgB;QAChB,YAAY;QACZ,aAAa;QACb,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,iBAAiB;QACjB,iBAAiB;QACjB,YAAY;QACZ,eAAe;KAChB,CAAC;IACF,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,iEAAiE;AACjE,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAC;IACvC,kBAAkB;IAClB,oBAAoB;IACpB,uBAAuB;IACvB,sBAAsB;CACvB,CAAC,CAAC;AAEH,mEAAmE;AACnE,yFAAyF;AACzF,MAAM,6BAA6B,GAAG,IAAI,GAAG,CAAC;IAC5C,kBAAkB;IAClB,oBAAoB;IACpB,uBAAuB;IACvB,sBAAsB;IACtB,0BAA0B;CAC3B,CAAC,CAAC;AAEH,MAAM,aAAa,GAAkB;IACnC;QACE,EAAE,EAAE,kBAAkB;QACtB,KAAK,EAAE,gCAAgC;QACvC,WAAW,EACT,qJAAqJ;QACvJ,QAAQ,EAAE,MAAM;QAChB,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;YAC5B,iFAAiF;YACjF,IAAI,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC;gBAAE,OAAO,EAAE,CAAC;YAC7C,OAAO,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;KACF;IACD;QACE,EAAE,EAAE,oBAAoB;QACxB,KAAK,EAAE,4DAA4D;QACnE,WAAW,EACT,qHAAqH;QACvH,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;YAC5B,yEAAyE;YACzE,MAAM,iBAAiB,GAAG;gBACxB,QAAQ;gBACR,WAAW;gBACX,WAAW;gBACX,QAAQ,EAAE,gCAAgC;gBAC1C,SAAS,EAAE,uBAAuB;gBAClC,UAAU,EAAE,gBAAgB;gBAC5B,aAAa,EAAE,qBAAqB;gBACpC,gBAAgB,EAAE,qBAAqB;gBACvC,yBAAyB,EAAE,mBAAmB;aAC/C,CAAC;YACF,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAAE,OAAO,EAAE,CAAC;YAE/D,mFAAmF;YACnF,0DAA0D;YAC1D,yDAAyD;YACzD,MAAM,YAAY,GAAG,2DAA2D,CAAC;YACjF,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACjD,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,GAAG;gBAAE,OAAO,EAAE,CAAC;YAEzD,oFAAoF;YACpF,OAAO,oBAAoB,CAAC,OAAO,EAAE,wBAAwB,EAAE,EAAE,CAAC,CAAC;QACrE,CAAC;KACF;IACD;QACE,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,sDAAsD;QAC7D,WAAW,EACT,oHAAoH;QACtH,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;YAC5B,+EAA+E;YAC/E,IAAI,SAAS,CAAC,QAAQ,CAAC;gBAAE,OAAO,EAAE,CAAC;YACnC,OAAO,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC;QAC/D,CAAC;KACF;IACD;QACE,EAAE,EAAE,sBAAsB;QAC1B,KAAK,EAAE,+CAA+C;QACtD,WAAW,EACT,mHAAmH;QACrH,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,oBAAoB,CAAC,OAAO,EAAE,0BAA0B,EAAE,CAAC,CAAC;KAClF;IACD;QACE,EAAE,EAAE,oBAAoB;QACxB,KAAK,EAAE,wCAAwC;QAC/C,WAAW,EACT,iHAAiH;QACnH,QAAQ,EAAE,MAAM;QAChB,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;YAC5B,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1D,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,IAAI,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;gBAClC,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO,oBAAoB,CAAC,OAAO,EAAE,wBAAwB,EAAE,CAAC,CAAC,CAAC;QACpE,CAAC;KACF;IACD;QACE,EAAE,EAAE,uBAAuB;QAC3B,KAAK,EAAE,6CAA6C;QACpD,WAAW,EACT,8FAA8F;QAChG,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,EAAE,CAAC,CAAC;KAC7E;IACD;QACE,EAAE,EAAE,0BAA0B;QAC9B,KAAK,EAAE,0CAA0C;QACjD,WAAW,EACT,sIAAsI;QACxI,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;YAC5B,IAAI,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;gBAClC,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,MAAM,mBAAmB,GAAG,IAAI,MAAM,CACpC,GAAG,wBAAwB,CAAC,MAAM,IAAI,mBAAmB,CAAC,MAAM,EAAE,EAClE,GAAG,CACJ,CAAC;YACF,MAAM,OAAO,GAAG,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC;YAEtE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC1B,MAAM,UAAU,GACd,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;oBAC7C,CAAC,CAAC,OAAO;yBACJ,KAAK,CAAC,IAAI,CAAC;yBACX,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;yBACpB,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;oBACjC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;gBACf,OAAO,uBAAuB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;YACtD,CAAC,CAAC,CAAC;QACL,CAAC;KACF;CACF,CAAC;AAEF,SAAS,kBAAkB,CAAC,QAAsB;IAChD,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAEvC,KAAK,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAChD,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,4BAA4B,CAAC;YAAE,SAAS;QAEnE,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACrD,MAAM,aAAa,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QAE9C,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,2CAA2C;YAC3C,IAAI,WAAW,CAAC,SAAS,IAAI,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnE,SAAS;YACX,CAAC;YACD,8DAA8D;YAC9D,IAAI,aAAa,IAAI,6BAA6B,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;gBAChE,SAAS;YACX,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC/C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAEnC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,EAAE,IAAI,QAAQ,EAAE,CAAC;YACrC,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YACpC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEtB,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,CAAC,UAAU;gBAAE,SAAS;YAE1B,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,QAAQ,EAAE,aAAa;gBACvB,QAAQ,EAAE;oBACR,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,UAAU,CAAC,IAAI;oBACrB,MAAM,EAAE,UAAU,CAAC,MAAM;iBAC1B;gBACD,QAAQ,EAAE;oBACR,UAAU,EAAE,OAAO,CAAC,MAAM;oBAC1B,UAAU,EAAE,UAAU,CAAC,OAAO;oBAC9B,UAAU,EAAE,OAAO;yBAChB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;yBACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACT,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;yBACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;yBAChF,IAAI,CAAC,IAAI,CAAC,CACd;iBACJ;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E,MAAM,UAAU,gBAAgB,CAAC,QAAsB;IACrD,MAAM,QAAQ,GAAc,EAAE,CAAC;IAE/B,sEAAsE;IACtE,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEzC,mDAAmD;IACnD,QAAQ,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE/C,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=obfuscation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obfuscation.test.d.ts","sourceRoot":"","sources":["../../../src/scanner/checks/obfuscation.test.ts"],"names":[],"mappings":""}