@aspect-guard/core 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -160,6 +160,11 @@ declare class ExtensionGuardScanner {
160
160
  private hashDatabase;
161
161
  constructor(options?: Partial<ScanOptions>);
162
162
  scan(options?: Partial<ScanOptions>): Promise<FullScanReport>;
163
+ /**
164
+ * Scan multiple extensions concurrently with a configurable pool size.
165
+ * Uses a simple semaphore pattern to limit concurrent operations.
166
+ */
167
+ private scanExtensionsConcurrently;
163
168
  private scanExtension;
164
169
  private calculateTrustScore;
165
170
  private calculateRiskLevel;
@@ -747,6 +752,6 @@ declare function generateBaseline(_extensionPaths: string[], _outputPath?: strin
747
752
  errors: string[];
748
753
  }>;
749
754
 
750
- declare const VERSION = "0.5.0";
755
+ declare const VERSION = "0.5.1";
751
756
 
752
757
  export { ALL_POPULAR_EXTENSIONS, type AdjustFindingsOptions, type AuditReport, type BundleDetectionResult, DETECTION_RULES, type DetectedIDE, type DetectionRule, type Evidence, type ExtensionCategory, ExtensionGuardScanner, type ExtensionHash, type ExtensionInfo, type ExtensionManifest, type Finding, type FindingCategory, type FullScanReport, type HashDatabase, IDE_PATHS, type InspectOptions, type IntegrityInfo, type IntegrityResult, type IntegrityStatus, JsonReporter, MEGA_POPULAR_EXTENSIONS, MarkdownReporter, POPULAR_EXTENSIONS, type PolicyAction, type PolicyConfig, PolicyEngine, type PolicyRules, type PolicyViolation, type PopularExtension, type Reporter, type ReporterOptions, type RiskLevel, RuleEngine, type RuleEngineOptions, SEVERITY_ORDER, SarifReporter, type ScanOptions, type ScanResult, type ScanSummary, type Severity, TRUSTED_EXTENSION_IDS, TRUSTED_PUBLISHERS, VERIFIED_PUBLISHERS, VERSION, addHash, adjustFindings, categorizeExtension, clearHashCache, collectFiles, compareSeverity, computeExtensionHashes, createHashRecord, detectBundle, detectIDEPaths, expandPath, generateBaseline, getDefaultDatabasePath, getHash, getIDEExtensionPath, getPopularityTier, getSupportedIDEs, isAtLeastSeverity, isBundleOutputPath, isIDEInstalled, isMegaPopular, isPopular, isTrustedExtension, isTrustedPublisher, isVerifiedPublisher, loadHashDatabase, loadPolicyConfig, readExtension, readExtensionsFromDirectory, registerBuiltInRules, ruleRegistry, saveHashDatabase, sha256, shouldCollectFile, shouldReduceSeverityForBundle, verifyIntegrity };
package/dist/index.js CHANGED
@@ -2178,11 +2178,8 @@ var ExtensionGuardScanner = class {
2178
2178
  }
2179
2179
  ide.extensionCount = allExtensions[i].length;
2180
2180
  }
2181
- const results = [];
2182
- for (const { ext } of extensionMap.values()) {
2183
- const result = await this.scanExtension(ext);
2184
- results.push(result);
2185
- }
2181
+ const extensions = Array.from(extensionMap.values()).map(({ ext }) => ext);
2182
+ const results = await this.scanExtensionsConcurrently(extensions, mergedOptions.concurrency);
2186
2183
  const summary = this.calculateSummary(results);
2187
2184
  return {
2188
2185
  scanId: randomUUID2(),
@@ -2199,6 +2196,29 @@ var ExtensionGuardScanner = class {
2199
2196
  scanDurationMs: Date.now() - startTime
2200
2197
  };
2201
2198
  }
2199
+ /**
2200
+ * Scan multiple extensions concurrently with a configurable pool size.
2201
+ * Uses a simple semaphore pattern to limit concurrent operations.
2202
+ */
2203
+ async scanExtensionsConcurrently(extensions, concurrency) {
2204
+ const results = new Array(extensions.length);
2205
+ let currentIndex = 0;
2206
+ const worker = async () => {
2207
+ while (currentIndex < extensions.length) {
2208
+ const index = currentIndex++;
2209
+ const ext = extensions[index];
2210
+ if (ext) {
2211
+ results[index] = await this.scanExtension(ext);
2212
+ }
2213
+ }
2214
+ };
2215
+ const workers = Array.from(
2216
+ { length: Math.min(concurrency, extensions.length) },
2217
+ () => worker()
2218
+ );
2219
+ await Promise.all(workers);
2220
+ return results.filter((r) => r !== void 0);
2221
+ }
2202
2222
  async scanExtension(ext) {
2203
2223
  const startTime = Date.now();
2204
2224
  const files = await collectFiles(ext.installPath);
@@ -2996,7 +3016,7 @@ var PolicyEngine = class {
2996
3016
  };
2997
3017
 
2998
3018
  // src/index.ts
2999
- var VERSION = "0.5.0";
3019
+ var VERSION = "0.5.1";
3000
3020
  export {
3001
3021
  ALL_POPULAR_EXTENSIONS,
3002
3022
  DETECTION_RULES,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/severity.ts","../src/scanner/scanner.ts","../src/scanner/ide-detector.ts","../src/scanner/extension-reader.ts","../src/scanner/file-collector.ts","../src/rules/rule-registry.ts","../src/rules/rule-engine.ts","../src/data/trusted-publishers.ts","../src/data/verified-publishers.ts","../src/data/popular-extensions.ts","../src/rules/finding-adjuster.ts","../src/rules/built-in/crit-data-exfiltration.ts","../src/rules/built-in/crit-remote-execution.ts","../src/rules/built-in/crit-credential-access.ts","../src/rules/built-in/high-suspicious-network.ts","../src/rules/built-in/high-obfuscated-code.ts","../src/rules/built-in/high-hardcoded-secret.ts","../src/rules/built-in/med-excessive-activation.ts","../src/rules/built-in/index.ts","../src/scanner/extension-categorizer.ts","../src/integrity/integrity-verifier.ts","../src/integrity/hash-database.ts","../src/analyzers/bundle-detector.ts","../src/reporter/json-reporter.ts","../src/reporter/sarif-reporter.ts","../src/reporter/markdown-reporter.ts","../src/policy/policy-loader.ts","../src/policy/policy-engine.ts","../src/index.ts"],"sourcesContent":["export type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';\n\nexport type RiskLevel = 'critical' | 'high' | 'medium' | 'low' | 'safe';\n\nexport const SEVERITY_ORDER: Record<Severity, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n info: 4,\n};\n\nexport function compareSeverity(a: Severity, b: Severity): number {\n return SEVERITY_ORDER[a] - SEVERITY_ORDER[b];\n}\n\nexport function isAtLeastSeverity(severity: Severity, minimum: Severity): boolean {\n return SEVERITY_ORDER[severity] <= SEVERITY_ORDER[minimum];\n}\n","import * as os from 'node:os';\nimport { randomUUID } from 'node:crypto';\nimport type {\n ScanOptions,\n FullScanReport,\n ScanResult,\n ScanSummary,\n RiskLevel,\n Severity,\n FindingCategory,\n DetectedIDE,\n ExtensionManifest,\n IntegrityInfo,\n} from '../types/index.js';\nimport { detectIDEPaths } from './ide-detector.js';\nimport { readExtensionsFromDirectory } from './extension-reader.js';\nimport { collectFiles } from './file-collector.js';\nimport { VERSION } from '../index.js';\nimport { RuleEngine } from '../rules/rule-engine.js';\nimport { adjustFindings } from '../rules/finding-adjuster.js';\nimport { registerBuiltInRules } from '../rules/built-in/index.js';\nimport { categorizeExtension } from './extension-categorizer.js';\nimport { verifyIntegrity, loadHashDatabase } from '../integrity/index.js';\nimport type { ExtensionHash } from '../integrity/index.js';\n\n// Register built-in rules once at module load\nlet rulesRegistered = false;\nfunction ensureRulesRegistered(): void {\n if (!rulesRegistered) {\n registerBuiltInRules();\n rulesRegistered = true;\n }\n}\n\nconst DEFAULT_OPTIONS: Required<ScanOptions> = {\n idePaths: [],\n autoDetect: true,\n severity: 'info',\n rules: [],\n skipRules: [],\n concurrency: 4,\n timeout: 30000,\n verifyIntegrity: false,\n hashDatabasePath: '',\n};\n\nconst SEVERITY_PENALTY: Record<Severity, number> = {\n critical: 35,\n high: 18,\n medium: 8,\n low: 3,\n info: 1,\n};\n\nexport class ExtensionGuardScanner {\n private options: Required<ScanOptions>;\n private ruleEngine: RuleEngine;\n private hashDatabase: Map<string, ExtensionHash> | null = null;\n\n constructor(options?: Partial<ScanOptions>) {\n ensureRulesRegistered();\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.ruleEngine = new RuleEngine({\n rules: this.options.rules.length > 0 ? this.options.rules : undefined,\n skipRules: this.options.skipRules.length > 0 ? this.options.skipRules : undefined,\n minSeverity: this.options.severity,\n });\n\n // Load hash database if integrity verification is enabled\n if (this.options.verifyIntegrity) {\n this.hashDatabase = loadHashDatabase(this.options.hashDatabasePath || undefined);\n }\n }\n\n async scan(options?: Partial<ScanOptions>): Promise<FullScanReport> {\n const startTime = Date.now();\n const mergedOptions = { ...this.options, ...options };\n\n // Detect IDE paths\n let ides: DetectedIDE[];\n if (mergedOptions.autoDetect && mergedOptions.idePaths.length === 0) {\n ides = detectIDEPaths();\n } else {\n ides = mergedOptions.idePaths.map((p) => ({\n name: 'Custom',\n path: p,\n extensionCount: 0,\n }));\n }\n\n // Collect all extensions\n const allExtensions = await Promise.all(\n ides.map((ide) => readExtensionsFromDirectory(ide.path))\n );\n\n const extensionMap = new Map<\n string,\n { ide: DetectedIDE; ext: Awaited<ReturnType<typeof readExtensionsFromDirectory>>[number] }\n >();\n for (let i = 0; i < ides.length; i++) {\n const ide = ides[i]!;\n for (const ext of allExtensions[i]!) {\n if (!extensionMap.has(ext.id)) {\n extensionMap.set(ext.id, { ide, ext });\n }\n }\n // Update extension count\n ide.extensionCount = allExtensions[i]!.length;\n }\n\n // Scan each extension\n const results: ScanResult[] = [];\n for (const { ext } of extensionMap.values()) {\n const result = await this.scanExtension(ext);\n results.push(result);\n }\n\n // Calculate summary\n const summary = this.calculateSummary(results);\n\n return {\n scanId: randomUUID(),\n version: VERSION,\n timestamp: new Date().toISOString(),\n environment: {\n os: `${os.platform()} ${os.release()}`,\n ides,\n },\n totalExtensions: Array.from(allExtensions).reduce((sum, arr) => sum + arr.length, 0),\n uniqueExtensions: extensionMap.size,\n results,\n summary,\n scanDurationMs: Date.now() - startTime,\n };\n }\n\n private async scanExtension(\n ext: Awaited<ReturnType<typeof readExtensionsFromDirectory>>[number]\n ): Promise<ScanResult> {\n const startTime = Date.now();\n const files = await collectFiles(ext.installPath);\n\n // Parse manifest for rule engine\n const manifestContent = files.get('package.json');\n let manifest: ExtensionManifest = {\n name: ext.id.split('.')[1] || ext.id,\n publisher: ext.publisher.name,\n version: ext.version,\n };\n if (manifestContent) {\n try {\n manifest = JSON.parse(manifestContent);\n } catch {\n // Use default manifest\n }\n }\n\n // Run rules\n const rawFindings = this.ruleEngine.run(files, manifest);\n\n // Infer extension category and adjust findings for expected behavior\n // Also apply soft trust for known publishers\n const category = categorizeExtension(manifest);\n const findings = adjustFindings(rawFindings, category, {\n publisher: ext.publisher.name,\n extensionId: ext.id,\n });\n\n // Calculate trust score\n const trustScore = this.calculateTrustScore(findings);\n let riskLevel = this.calculateRiskLevel(trustScore, findings);\n\n // Verify integrity if enabled\n let integrity: IntegrityInfo | undefined;\n if (this.options.verifyIntegrity && this.hashDatabase) {\n const result = verifyIntegrity(ext.id, ext.version, files, this.hashDatabase);\n integrity = {\n status: result.status,\n modifications: result.modifications,\n hash: result.computedHashes?.combinedHash,\n };\n\n // If extension is modified, override risk level to critical\n if (result.status === 'modified') {\n riskLevel = 'critical';\n // Add a synthetic finding for the integrity violation\n findings.unshift({\n id: `integrity-${ext.id}`,\n ruleId: 'EG-CRIT-100',\n severity: 'critical',\n category: 'supply-chain',\n title: 'Extension Integrity Compromised',\n description:\n `Extension files have been modified from known-good version. Modifications: ${\n result.modifications?.manifest ? 'manifest ' : ''\n }${result.modifications?.content ? 'content ' : ''}${\n result.modifications?.structure ? 'structure' : ''\n }`.trim(),\n evidence: {\n filePath: ext.installPath,\n matchedPattern: 'integrity-violation',\n },\n remediation:\n 'Reinstall the extension from the official marketplace. If this persists, report to the extension author.',\n });\n }\n } else if (this.options.verifyIntegrity) {\n integrity = { status: 'skipped' };\n }\n\n return {\n extensionId: ext.id,\n displayName: ext.displayName,\n version: ext.version,\n trustScore,\n riskLevel,\n findings,\n metadata: ext,\n analyzedFiles: files.size,\n scanDurationMs: Date.now() - startTime,\n integrity,\n };\n }\n\n private calculateTrustScore(findings: ScanResult['findings']): number {\n let score = 100;\n\n // Count findings by rule to avoid excessive penalty from bundled code\n const findingsByRule = new Map<string, number>();\n\n for (const finding of findings) {\n const count = findingsByRule.get(finding.ruleId) ?? 0;\n\n // Cap each rule's penalty contribution (max 5 findings per rule for scoring)\n // This prevents bundled code with 1000+ similar patterns from zeroing the score\n if (count < 5) {\n score -= SEVERITY_PENALTY[finding.severity];\n findingsByRule.set(finding.ruleId, count + 1);\n }\n }\n\n // Clamp to [0, 100]\n return Math.max(0, Math.min(100, score));\n }\n\n private calculateRiskLevel(trustScore: number, findings: ScanResult['findings']): RiskLevel {\n // Only non-downgraded critical/high findings affect risk level\n // (downgraded findings have \"[Downgraded:\" in description)\n const realFindings = findings.filter((f) => !f.description?.includes('[Downgraded:'));\n\n // If any real critical finding, always critical\n if (realFindings.some((f) => f.severity === 'critical')) {\n return 'critical';\n }\n // If any real high finding, at least high\n if (realFindings.some((f) => f.severity === 'high')) {\n return 'high';\n }\n\n // Otherwise, base on trust score\n if (trustScore >= 90) return 'safe';\n if (trustScore >= 70) return 'low';\n if (trustScore >= 45) return 'medium';\n if (trustScore >= 20) return 'high';\n return 'critical';\n }\n\n private calculateSummary(results: ScanResult[]): ScanSummary {\n const byRiskLevel: Record<RiskLevel, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n safe: 0,\n };\n\n const bySeverity: Record<Severity, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n info: 0,\n };\n\n const byCategory: Partial<Record<FindingCategory, number>> = {};\n\n for (const result of results) {\n byRiskLevel[result.riskLevel]++;\n\n for (const finding of result.findings) {\n bySeverity[finding.severity]++;\n byCategory[finding.category] = (byCategory[finding.category] ?? 0) + 1;\n }\n }\n\n // Collect top findings (sorted by severity)\n const allFindings = results.flatMap((r) => r.findings);\n const severityOrder: Record<Severity, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n info: 4,\n };\n const topFindings = allFindings\n .sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity])\n .slice(0, 10);\n\n // Calculate overall health score\n const totalExtensions = results.length;\n const safeCount = byRiskLevel.safe + byRiskLevel.low;\n const overallHealthScore =\n totalExtensions > 0 ? Math.round((safeCount / totalExtensions) * 100) : 100;\n\n return {\n byRiskLevel,\n bySeverity,\n byCategory,\n topFindings,\n overallHealthScore,\n };\n }\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { DetectedIDE } from '../types/index.js';\n\n/**\n * IDE extension paths organized by IDE name.\n * Each IDE has multiple possible paths to support:\n * - Different OS (Windows, macOS, Linux)\n * - Different installation methods (user, system, portable)\n * - Remote development scenarios (SSH, WSL, containers)\n *\n * Paths use these placeholders:\n * - ~ : User home directory\n * - %USERPROFILE% : Windows user profile\n * - %APPDATA% : Windows AppData/Roaming\n * - %LOCALAPPDATA% : Windows AppData/Local\n *\n * References:\n * - https://code.visualstudio.com/docs/editor/extension-marketplace\n * - https://code.visualstudio.com/docs/remote/troubleshooting\n * - https://vscodium.com/\n * - https://zed.dev/docs/extensions/installing-extensions\n */\nexport const IDE_PATHS: Record<string, string[]> = {\n // VS Code - Standard installation\n 'VS Code': [\n // Linux & macOS\n '~/.vscode/extensions',\n // Windows\n '%USERPROFILE%/.vscode/extensions',\n '%USERPROFILE%\\\\.vscode\\\\extensions',\n ],\n\n // VS Code Insiders - Preview builds\n 'VS Code Insiders': [\n // Linux & macOS\n '~/.vscode-insiders/extensions',\n // Windows\n '%USERPROFILE%/.vscode-insiders/extensions',\n '%USERPROFILE%\\\\.vscode-insiders\\\\extensions',\n ],\n\n // VS Code Server - Remote SSH connections\n 'VS Code Server': ['~/.vscode-server/extensions'],\n\n // VS Code Server Insiders - Remote SSH for Insiders\n 'VS Code Server Insiders': ['~/.vscode-server-insiders/extensions'],\n\n // Cursor - AI-powered code editor (VS Code fork)\n // https://cursor.com\n Cursor: [\n // Linux & macOS\n '~/.cursor/extensions',\n // Windows\n '%USERPROFILE%/.cursor/extensions',\n '%USERPROFILE%\\\\.cursor\\\\extensions',\n // macOS alternate location\n '~/Library/Application Support/Cursor/User/extensions',\n ],\n\n // Cursor Server - Remote Cursor connections\n 'Cursor Server': ['~/.cursor-server/extensions'],\n\n // Windsurf - Codeium AI IDE (VS Code fork)\n // https://codeium.com/windsurf\n Windsurf: [\n // Linux & macOS\n '~/.windsurf/extensions',\n // Windows\n '%USERPROFILE%/.windsurf/extensions',\n '%USERPROFILE%\\\\.windsurf\\\\extensions',\n // macOS alternate location\n '~/Library/Application Support/Windsurf/extensions',\n ],\n\n // Windsurf Server - Remote Windsurf connections\n 'Windsurf Server': ['~/.windsurf-server/extensions'],\n\n // Trae - ByteDance AI IDE (VS Code fork)\n // https://www.trae.ai / https://www.marscode.com\n Trae: [\n // Linux & macOS\n '~/.trae/extensions',\n // Windows\n '%USERPROFILE%/.trae/extensions',\n '%USERPROFILE%\\\\.trae\\\\extensions',\n ],\n\n // VSCodium - Open source VS Code without telemetry\n // https://vscodium.com\n VSCodium: [\n // Linux & macOS\n '~/.vscode-oss/extensions',\n // Windows\n '%USERPROFILE%/.vscode-oss/extensions',\n '%USERPROFILE%\\\\.vscode-oss\\\\extensions',\n // Flatpak installation (Linux)\n '~/.var/app/com.vscodium.codium/data/codium/extensions',\n ],\n\n // VSCodium Insiders\n 'VSCodium Insiders': [\n '~/.vscode-oss-insiders/extensions',\n '%USERPROFILE%/.vscode-oss-insiders/extensions',\n ],\n\n // Code - OSS (open source build from Microsoft repo)\n 'Code - OSS': ['~/.config/Code - OSS/extensions', '~/.vscode-oss/extensions'],\n\n // Positron - Posit's data science IDE (VS Code fork)\n // https://github.com/posit-dev/positron\n Positron: [\n '~/.positron/extensions',\n '%USERPROFILE%/.positron/extensions',\n '~/Library/Application Support/Positron/extensions',\n ],\n\n // Theia - Eclipse Theia IDE (VS Code compatible)\n // https://theia-ide.org\n Theia: ['~/.theia/extensions', '%USERPROFILE%/.theia/extensions'],\n\n // OpenVSCode Server - Web-based VS Code\n // https://github.com/gitpod-io/openvscode-server\n 'OpenVSCode Server': ['~/.openvscode-server/extensions'],\n\n // code-server - VS Code in the browser\n // https://github.com/coder/code-server\n 'code-server': ['~/.local/share/code-server/extensions', '~/.config/code-server/extensions'],\n\n // GitHub Codespaces (when accessed locally)\n 'GitHub Codespaces': ['~/.codespaces/.vscode-remote/extensions'],\n\n // Gitpod\n Gitpod: ['/workspace/.gitpod/extensions', '~/.gitpod/extensions'],\n\n // DevPod\n DevPod: ['~/.devpod/extensions'],\n\n // Lapce - Lightning-fast native code editor (has its own extension format but partially compatible)\n // https://lapce.dev\n // Note: Lapce uses a different extension format, included for future compatibility\n // Lapce: [\n // '~/.lapce/plugins',\n // '~/Library/Application Support/Lapce/plugins',\n // ],\n\n // Zed - High-performance editor (different extension format, not VS Code compatible)\n // https://zed.dev\n // Note: Zed uses its own extension format, not VS Code compatible\n // Included as reference for potential future support\n // Zed: [\n // '~/Library/Application Support/Zed/extensions',\n // '~/.local/share/zed/extensions',\n // ],\n};\n\n/**\n * Expand path placeholders to actual paths\n */\nexport function expandPath(inputPath: string): string {\n let result = inputPath;\n const home = os.homedir();\n\n // Expand ~ to home directory\n if (result.startsWith('~/')) {\n result = path.join(home, result.slice(2));\n } else if (result.startsWith('~\\\\')) {\n result = path.join(home, result.slice(2));\n } else if (result === '~') {\n result = home;\n }\n\n // Windows environment variables\n if (process.platform === 'win32') {\n result = result.replace(/%USERPROFILE%/gi, home);\n result = result.replace(\n /%APPDATA%/gi,\n process.env.APPDATA || path.join(home, 'AppData', 'Roaming')\n );\n result = result.replace(\n /%LOCALAPPDATA%/gi,\n process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local')\n );\n } else {\n // On non-Windows, just remove Windows-style placeholders if they exist\n result = result.replace(/%USERPROFILE%/gi, home);\n }\n\n // Normalize path separators for current OS\n return path.normalize(result);\n}\n\n/**\n * Count extensions in a directory\n */\nfunction countExtensions(dirPath: string): number {\n try {\n const entries = fs.readdirSync(dirPath, { withFileTypes: true });\n // Count directories that look like extensions (contain package.json or have publisher.name format)\n return entries.filter((entry) => {\n if (!entry.isDirectory()) return false;\n // Skip hidden directories and common non-extension directories\n if (entry.name.startsWith('.')) return false;\n if (entry.name === 'node_modules') return false;\n return true;\n }).length;\n } catch {\n return 0;\n }\n}\n\n/**\n * Detect all installed IDE extension paths\n */\nexport function detectIDEPaths(): DetectedIDE[] {\n const detected: DetectedIDE[] = [];\n\n for (const [ideName, paths] of Object.entries(IDE_PATHS)) {\n for (const idePath of paths) {\n const expandedPath = expandPath(idePath);\n if (fs.existsSync(expandedPath)) {\n const extensionCount = countExtensions(expandedPath);\n // Only add if there are actually extensions (or the directory exists)\n if (extensionCount > 0) {\n detected.push({\n name: ideName,\n path: expandedPath,\n extensionCount,\n });\n break; // Found this IDE, move to next\n }\n }\n }\n }\n\n return detected;\n}\n\n/**\n * Get list of all supported IDE names\n */\nexport function getSupportedIDEs(): string[] {\n return Object.keys(IDE_PATHS);\n}\n\n/**\n * Check if a specific IDE is installed\n */\nexport function isIDEInstalled(ideName: string): boolean {\n const paths = IDE_PATHS[ideName];\n if (!paths) return false;\n\n return paths.some((p) => {\n const expanded = expandPath(p);\n return fs.existsSync(expanded) && countExtensions(expanded) > 0;\n });\n}\n\n/**\n * Get the extension path for a specific IDE\n */\nexport function getIDEExtensionPath(ideName: string): string | null {\n const paths = IDE_PATHS[ideName];\n if (!paths) return null;\n\n for (const p of paths) {\n const expanded = expandPath(p);\n if (fs.existsSync(expanded)) {\n return expanded;\n }\n }\n\n return null;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { ExtensionInfo, ExtensionManifest } from '../types/index.js';\n\nexport async function readExtension(extensionPath: string): Promise<ExtensionInfo | null> {\n try {\n const packageJsonPath = path.join(extensionPath, 'package.json');\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const manifest: ExtensionManifest = JSON.parse(content);\n\n if (!manifest.name || !manifest.publisher || !manifest.version) {\n return null;\n }\n\n const stats = await getDirectoryStats(extensionPath);\n\n const repository =\n typeof manifest.repository === 'string' ? manifest.repository : manifest.repository?.url;\n\n return {\n id: `${manifest.publisher}.${manifest.name}`,\n displayName: manifest.displayName ?? manifest.name,\n version: manifest.version,\n publisher: {\n name: manifest.publisher,\n verified: false,\n },\n description: manifest.description ?? '',\n categories: manifest.categories ?? [],\n activationEvents: manifest.activationEvents ?? [],\n extensionDependencies: manifest.extensionDependencies ?? [],\n installPath: extensionPath,\n engines: { vscode: manifest.engines?.vscode ?? '*' },\n repository,\n license: manifest.license,\n fileCount: stats.fileCount,\n totalSize: stats.totalSize,\n };\n } catch {\n return null;\n }\n}\n\nasync function getDirectoryStats(\n dirPath: string\n): Promise<{ fileCount: number; totalSize: number }> {\n let fileCount = 0;\n let totalSize = 0;\n\n async function walk(currentPath: string): Promise<void> {\n try {\n const entries = await fs.readdir(currentPath, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(currentPath, entry.name);\n if (entry.isDirectory()) {\n if (entry.name !== 'node_modules') {\n await walk(fullPath);\n }\n } else {\n fileCount++;\n try {\n const stat = await fs.stat(fullPath);\n totalSize += stat.size;\n } catch {\n // Skip files we can't stat\n }\n }\n }\n } catch {\n // Skip directories we can't read\n }\n }\n\n await walk(dirPath);\n return { fileCount, totalSize };\n}\n\nexport async function readExtensionsFromDirectory(directoryPath: string): Promise<ExtensionInfo[]> {\n const extensions: ExtensionInfo[] = [];\n\n try {\n const entries = await fs.readdir(directoryPath, { withFileTypes: true });\n const directories = entries.filter((entry) => entry.isDirectory());\n\n const results = await Promise.all(\n directories.map((dir) => readExtension(path.join(directoryPath, dir.name)))\n );\n\n for (const result of results) {\n if (result) {\n extensions.push(result);\n }\n }\n } catch {\n return [];\n }\n\n return extensions;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nconst COLLECTED_EXTENSIONS = new Set(['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs', '.json']);\n\nconst IGNORED_DIRECTORIES = new Set(['node_modules', '.git', '.svn', '.hg', '__pycache__']);\n\nconst IGNORED_PATTERNS = [/\\.min\\.js$/, /\\.map$/, /\\.d\\.ts$/];\n\nconst MAX_FILE_SIZE = 1024 * 1024; // 1MB\n\nexport function shouldCollectFile(filePath: string): boolean {\n const ext = path.extname(filePath).toLowerCase();\n\n if (!COLLECTED_EXTENSIONS.has(ext)) {\n return false;\n }\n\n const parts = filePath.split(path.sep);\n for (const part of parts) {\n if (IGNORED_DIRECTORIES.has(part)) {\n return false;\n }\n }\n\n for (const pattern of IGNORED_PATTERNS) {\n if (pattern.test(filePath)) {\n return false;\n }\n }\n\n return true;\n}\n\nexport async function collectFiles(extensionPath: string): Promise<Map<string, string>> {\n const files = new Map<string, string>();\n\n async function walk(currentPath: string, relativePath: string): Promise<void> {\n try {\n const entries = await fs.readdir(currentPath, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(currentPath, entry.name);\n const relPath = relativePath ? path.join(relativePath, entry.name) : entry.name;\n\n if (entry.isDirectory()) {\n if (!IGNORED_DIRECTORIES.has(entry.name)) {\n await walk(fullPath, relPath);\n }\n } else if (entry.isFile()) {\n if (shouldCollectFile(relPath)) {\n try {\n const stat = await fs.stat(fullPath);\n if (stat.size <= MAX_FILE_SIZE) {\n const content = await fs.readFile(fullPath, 'utf-8');\n files.set(relPath, content);\n }\n } catch {\n // Skip files we can't read\n }\n }\n }\n }\n } catch {\n // Skip directories we can't access\n }\n }\n\n await walk(extensionPath, '');\n return files;\n}\n","import type { DetectionRule } from './rule.interface.js';\n\nclass RuleRegistry {\n private rules: Map<string, DetectionRule> = new Map();\n\n register(rule: DetectionRule): void {\n this.rules.set(rule.id, rule);\n }\n\n get(id: string): DetectionRule | undefined {\n return this.rules.get(id);\n }\n\n getAll(): DetectionRule[] {\n return Array.from(this.rules.values());\n }\n\n getEnabled(): DetectionRule[] {\n return this.getAll().filter((rule) => rule.enabled);\n }\n\n getByCategory(category: string): DetectionRule[] {\n return this.getAll().filter((rule) => rule.category === category);\n }\n\n getBySeverity(severity: string): DetectionRule[] {\n return this.getAll().filter((rule) => rule.severity === severity);\n }\n\n clear(): void {\n this.rules.clear();\n }\n}\n\nexport const ruleRegistry = new RuleRegistry();\n","import type { ExtensionManifest, Finding, Severity } from '../types/index.js';\nimport { SEVERITY_ORDER } from '../types/index.js';\nimport type { DetectionRule, Evidence } from './rule.interface.js';\nimport { ruleRegistry } from './rule-registry.js';\nimport { randomUUID } from 'node:crypto';\n\nexport interface RuleEngineOptions {\n rules?: string[];\n skipRules?: string[];\n minSeverity?: Severity;\n}\n\nexport class RuleEngine {\n private options: RuleEngineOptions;\n\n constructor(options: RuleEngineOptions = {}) {\n this.options = options;\n }\n\n run(files: Map<string, string>, manifest: ExtensionManifest): Finding[] {\n const findings: Finding[] = [];\n const rules = this.getApplicableRules();\n\n for (const rule of rules) {\n try {\n const evidences = rule.detect(files, manifest);\n for (const evidence of evidences) {\n findings.push(this.createFinding(rule, evidence));\n }\n } catch {\n // Rule failed, continue with other rules\n }\n }\n\n return findings;\n }\n\n private getApplicableRules(): DetectionRule[] {\n let rules = ruleRegistry.getEnabled();\n\n if (this.options.rules && this.options.rules.length > 0) {\n rules = rules.filter((r) => this.options.rules!.includes(r.id));\n }\n\n if (this.options.skipRules && this.options.skipRules.length > 0) {\n rules = rules.filter((r) => !this.options.skipRules!.includes(r.id));\n }\n\n if (this.options.minSeverity) {\n const minOrder = SEVERITY_ORDER[this.options.minSeverity];\n rules = rules.filter((r) => SEVERITY_ORDER[r.severity] <= minOrder);\n }\n\n return rules;\n }\n\n private createFinding(rule: DetectionRule, evidence: Evidence): Finding {\n return {\n id: randomUUID(),\n ruleId: rule.id,\n severity: rule.severity,\n category: rule.category,\n title: rule.name,\n description: rule.description,\n evidence: {\n filePath: evidence.filePath,\n lineNumber: evidence.lineNumber,\n columnNumber: evidence.columnNumber,\n lineContent: evidence.lineContent,\n contextBefore: evidence.contextBefore,\n contextAfter: evidence.contextAfter,\n matchedPattern: evidence.matchedPattern,\n snippet: evidence.snippet,\n },\n mitreAttackId: rule.mitreAttackId,\n };\n }\n}\n","/**\n * List of well-known, trusted publishers.\n *\n * Extensions from these publishers receive \"soft trust\" treatment:\n * - Their findings are downgraded one additional severity level\n * - They are NOT completely bypassed (supply chain attacks can hit anyone)\n *\n * This list is intentionally conservative and includes only:\n * - Major IDE vendors (Microsoft, GitHub)\n * - Well-established tool vendors with long track records\n */\nexport const TRUSTED_PUBLISHERS = [\n // Microsoft official\n 'ms-python',\n 'ms-vscode',\n 'ms-dotnettools',\n 'ms-azuretools',\n 'ms-toolsai',\n 'microsoft',\n 'vscode',\n\n // GitHub\n 'github',\n\n // Major language support\n 'golang',\n 'rust-lang',\n 'redhat',\n 'oracle',\n 'julialang',\n\n // Major tool vendors\n 'esbenp', // Prettier\n 'dbaeumer', // ESLint\n 'eamodio', // GitLens\n\n // Cloud providers\n 'amazonwebservices',\n 'googlecloudtools',\n 'hashicorp',\n\n // Other major vendors\n 'jetbrains',\n 'docker',\n 'mongodb',\n 'prisma',\n 'vscjava', // Microsoft Java\n\n // Popular developer tool vendors\n 'formulahendry', // Code Runner (10M+ downloads)\n 'ritwickdey', // Live Server (50M+ downloads)\n 'humao', // REST Client (5M+ downloads)\n 'rangav', // Thunder Client (3M+ downloads)\n 'mtxr', // SQLTools\n 'cweijan', // Database Client\n\n // Remote development\n 'ms-vscode-remote', // Remote-SSH, Dev Containers, WSL\n\n // Testing\n 'hbenl', // Test Explorer UI\n 'firsttris', // Jest Runner\n 'orta', // vscode-jest\n\n // Notebooks\n 'ms-toolsai', // Jupyter\n];\n\n/**\n * Specific extension IDs that are trusted regardless of publisher.\n * Use this for known extensions from smaller publishers.\n */\nexport const TRUSTED_EXTENSION_IDS = [\n // These are explicitly trusted extension IDs\n 'github.copilot',\n 'github.copilot-chat',\n 'ms-python.python',\n 'ms-python.vscode-pylance',\n 'ms-vscode.cpptools',\n 'golang.go',\n 'rust-lang.rust-analyzer',\n];\n\n/**\n * Check if an extension is from a trusted publisher.\n */\nexport function isTrustedPublisher(publisher: string): boolean {\n const normalized = publisher.toLowerCase();\n return TRUSTED_PUBLISHERS.some((p) => normalized === p.toLowerCase());\n}\n\n/**\n * Check if an extension ID is explicitly trusted.\n */\nexport function isTrustedExtension(extensionId: string): boolean {\n const normalized = extensionId.toLowerCase();\n return TRUSTED_EXTENSION_IDS.some((id) => normalized === id.toLowerCase());\n}\n","/**\n * List of verified publishers from VS Code Marketplace.\n *\n * These publishers have undergone verification by Microsoft and display\n * a verified badge on the marketplace. Extensions from verified publishers\n * are treated similarly to trusted publishers.\n *\n * Note: This list is maintained manually based on known verified publishers.\n * In the future, this could be fetched from the marketplace API.\n */\nexport const VERIFIED_PUBLISHERS = [\n // Microsoft & GitHub (already trusted, but also verified)\n 'microsoft',\n 'ms-python',\n 'ms-vscode',\n 'ms-dotnettools',\n 'ms-azuretools',\n 'ms-toolsai',\n 'ms-vscode-remote',\n 'ms-kubernetes-tools',\n 'ms-playwright',\n 'vscode',\n 'github',\n 'vscjava',\n\n // Major cloud providers (verified)\n 'amazonwebservices',\n 'googlecloudtools',\n 'hashicorp',\n\n // Major language/framework vendors (verified)\n 'golang',\n 'rust-lang',\n 'redhat',\n 'oracle',\n 'julialang',\n 'dart-code',\n 'flutter',\n 'svelte',\n 'vue',\n 'angular',\n 'astro-build',\n\n // Major tool vendors (verified)\n 'jetbrains',\n 'docker',\n 'mongodb',\n 'prisma',\n 'atlassian',\n 'gitlab',\n 'sourcegraph',\n 'snyk-security',\n 'sonarqube',\n 'datadog',\n\n // Popular extension vendors (verified)\n 'davidanson', // markdownlint\n 'esbenp', // Prettier\n 'dbaeumer', // ESLint\n 'eamodio', // GitLens\n 'streetsidesoftware', // Code Spell Checker\n 'editorconfig',\n 'christian-kohler', // Path Intellisense\n 'visualstudioexptteam', // IntelliCode\n 'bierner', // Markdown Preview\n 'jock', // SVG Viewer\n 'pkief', // Material Icon Theme\n 'zhuangtongfa', // One Dark Pro\n 'mechatroner', // Rainbow CSV\n];\n\n/**\n * Check if a publisher is verified on the marketplace.\n */\nexport function isVerifiedPublisher(publisher: string): boolean {\n const normalized = publisher.toLowerCase();\n return VERIFIED_PUBLISHERS.some((p) => normalized === p.toLowerCase());\n}\n","/**\n * List of popular extensions with high download counts.\n *\n * Extensions with millions of downloads have been vetted by the community\n * through widespread usage. Supply chain attacks on these would be extremely\n * visible and risky for attackers.\n *\n * Threshold tiers:\n * - 10M+ downloads: Highest trust (downgrade by 2 severity levels)\n * - 1M+ downloads: High trust (downgrade by 1 severity level)\n *\n * Note: This data is manually maintained. In the future, this could be\n * fetched from the marketplace API and cached locally.\n *\n * Last updated: 2026-02\n */\n\nexport interface PopularExtension {\n id: string;\n downloads: number;\n tier: 'mega' | 'popular'; // mega: 10M+, popular: 1M+\n}\n\n/**\n * Extensions with 10M+ downloads (mega popular)\n */\nexport const MEGA_POPULAR_EXTENSIONS: PopularExtension[] = [\n // Python ecosystem\n { id: 'ms-python.python', downloads: 120_000_000, tier: 'mega' },\n { id: 'ms-python.vscode-pylance', downloads: 80_000_000, tier: 'mega' },\n\n // C/C++\n { id: 'ms-vscode.cpptools', downloads: 60_000_000, tier: 'mega' },\n\n // GitHub Copilot\n { id: 'github.copilot', downloads: 50_000_000, tier: 'mega' },\n { id: 'github.copilot-chat', downloads: 30_000_000, tier: 'mega' },\n\n // ESLint & Prettier\n { id: 'dbaeumer.vscode-eslint', downloads: 45_000_000, tier: 'mega' },\n { id: 'esbenp.prettier-vscode', downloads: 50_000_000, tier: 'mega' },\n\n // Live Server\n { id: 'ritwickdey.liveserver', downloads: 60_000_000, tier: 'mega' },\n\n // GitLens\n { id: 'eamodio.gitlens', downloads: 40_000_000, tier: 'mega' },\n\n // Docker\n { id: 'ms-azuretools.vscode-docker', downloads: 35_000_000, tier: 'mega' },\n\n // Remote Development\n { id: 'ms-vscode-remote.remote-ssh', downloads: 25_000_000, tier: 'mega' },\n { id: 'ms-vscode-remote.remote-containers', downloads: 20_000_000, tier: 'mega' },\n { id: 'ms-vscode-remote.remote-wsl', downloads: 20_000_000, tier: 'mega' },\n\n // IntelliCode\n { id: 'visualstudioexptteam.vscodeintellicode', downloads: 40_000_000, tier: 'mega' },\n\n // Path Intellisense\n { id: 'christian-kohler.path-intellisense', downloads: 20_000_000, tier: 'mega' },\n\n // Material Icon Theme\n { id: 'pkief.material-icon-theme', downloads: 30_000_000, tier: 'mega' },\n\n // One Dark Pro\n { id: 'zhuangtongfa.material-theme', downloads: 15_000_000, tier: 'mega' },\n\n // Bracket Pair Colorizer (now built-in but still installed)\n { id: 'coenraads.bracket-pair-colorizer-2', downloads: 12_000_000, tier: 'mega' },\n\n // Code Runner\n { id: 'formulahendry.code-runner', downloads: 20_000_000, tier: 'mega' },\n\n // Auto Rename Tag\n { id: 'formulahendry.auto-rename-tag', downloads: 18_000_000, tier: 'mega' },\n\n // Code Spell Checker\n { id: 'streetsidesoftware.code-spell-checker', downloads: 15_000_000, tier: 'mega' },\n\n // Markdown All in One\n { id: 'yzhang.markdown-all-in-one', downloads: 12_000_000, tier: 'mega' },\n\n // Debugger for Chrome (deprecated but still installed)\n { id: 'msjsdiag.debugger-for-chrome', downloads: 25_000_000, tier: 'mega' },\n\n // Go\n { id: 'golang.go', downloads: 15_000_000, tier: 'mega' },\n\n // Java\n { id: 'redhat.java', downloads: 20_000_000, tier: 'mega' },\n { id: 'vscjava.vscode-java-debug', downloads: 15_000_000, tier: 'mega' },\n { id: 'vscjava.vscode-java-pack', downloads: 18_000_000, tier: 'mega' },\n\n // C#\n { id: 'ms-dotnettools.csharp', downloads: 25_000_000, tier: 'mega' },\n];\n\n/**\n * Extensions with 1M-10M downloads (popular)\n */\nexport const POPULAR_EXTENSIONS: PopularExtension[] = [\n // REST Clients\n { id: 'humao.rest-client', downloads: 5_000_000, tier: 'popular' },\n { id: 'rangav.vscode-thunder-client', downloads: 3_000_000, tier: 'popular' },\n\n // Database\n { id: 'mtxr.sqltools', downloads: 4_000_000, tier: 'popular' },\n { id: 'cweijan.vscode-database-client2', downloads: 2_000_000, tier: 'popular' },\n\n // Jupyter\n { id: 'ms-toolsai.jupyter', downloads: 8_000_000, tier: 'popular' },\n { id: 'ms-toolsai.jupyter-keymap', downloads: 5_000_000, tier: 'popular' },\n\n // Kubernetes\n { id: 'ms-kubernetes-tools.vscode-kubernetes-tools', downloads: 4_000_000, tier: 'popular' },\n\n // Vue / React / Angular\n { id: 'vue.volar', downloads: 8_000_000, tier: 'popular' },\n { id: 'dsznajder.es7-react-js-snippets', downloads: 9_000_000, tier: 'popular' },\n { id: 'angular.ng-template', downloads: 5_000_000, tier: 'popular' },\n\n // Svelte\n { id: 'svelte.svelte-vscode', downloads: 3_000_000, tier: 'popular' },\n\n // Astro\n { id: 'astro-build.astro-vscode', downloads: 2_000_000, tier: 'popular' },\n\n // Tailwind CSS\n { id: 'bradlc.vscode-tailwindcss', downloads: 8_000_000, tier: 'popular' },\n\n // YAML\n { id: 'redhat.vscode-yaml', downloads: 9_000_000, tier: 'popular' },\n\n // XML\n { id: 'redhat.vscode-xml', downloads: 6_000_000, tier: 'popular' },\n\n // Rust\n { id: 'rust-lang.rust-analyzer', downloads: 5_000_000, tier: 'popular' },\n\n // PowerShell\n { id: 'ms-vscode.powershell', downloads: 8_000_000, tier: 'popular' },\n\n // Terraform\n { id: 'hashicorp.terraform', downloads: 9_000_000, tier: 'popular' },\n\n // TODO Highlight\n { id: 'wayou.vscode-todo-highlight', downloads: 6_000_000, tier: 'popular' },\n\n // Bookmarks\n { id: 'alefragnani.bookmarks', downloads: 5_000_000, tier: 'popular' },\n\n // Project Manager\n { id: 'alefragnani.project-manager', downloads: 4_000_000, tier: 'popular' },\n\n // Rainbow CSV\n { id: 'mechatroner.rainbow-csv', downloads: 4_000_000, tier: 'popular' },\n\n // Markdown Preview\n { id: 'bierner.markdown-preview-github-styles', downloads: 3_000_000, tier: 'popular' },\n\n // markdownlint\n { id: 'davidanson.vscode-markdownlint', downloads: 6_000_000, tier: 'popular' },\n\n // Error Lens\n { id: 'usernamehw.errorlens', downloads: 5_000_000, tier: 'popular' },\n\n // Playwright\n { id: 'ms-playwright.playwright', downloads: 2_000_000, tier: 'popular' },\n\n // Jest\n { id: 'orta.vscode-jest', downloads: 3_000_000, tier: 'popular' },\n\n // Swagger / OpenAPI\n { id: 'arjun.swagger-viewer', downloads: 2_000_000, tier: 'popular' },\n\n // Figma\n { id: 'figma.figma-vscode-extension', downloads: 1_000_000, tier: 'popular' },\n\n // Atlassian\n { id: 'atlassian.atlascode', downloads: 2_000_000, tier: 'popular' },\n];\n\n/**\n * All popular extensions combined\n */\nexport const ALL_POPULAR_EXTENSIONS: PopularExtension[] = [\n ...MEGA_POPULAR_EXTENSIONS,\n ...POPULAR_EXTENSIONS,\n];\n\n/**\n * Get popularity tier for an extension.\n * Returns null if not in the popular extensions list.\n */\nexport function getPopularityTier(extensionId: string): 'mega' | 'popular' | null {\n const normalized = extensionId.toLowerCase();\n const ext = ALL_POPULAR_EXTENSIONS.find((e) => e.id.toLowerCase() === normalized);\n return ext?.tier ?? null;\n}\n\n/**\n * Check if an extension is mega popular (10M+ downloads)\n */\nexport function isMegaPopular(extensionId: string): boolean {\n return getPopularityTier(extensionId) === 'mega';\n}\n\n/**\n * Check if an extension is popular (1M+ downloads)\n */\nexport function isPopular(extensionId: string): boolean {\n return getPopularityTier(extensionId) !== null;\n}\n","import type { Finding, Severity } from '../types/index.js';\nimport type { ExtensionCategory } from '../scanner/extension-categorizer.js';\nimport { isTrustedPublisher, isTrustedExtension } from '../data/trusted-publishers.js';\nimport { isVerifiedPublisher } from '../data/verified-publishers.js';\nimport { getPopularityTier } from '../data/popular-extensions.js';\n\n/**\n * Severity one level below the given severity.\n * Used to downgrade findings that match expected behavior for the category.\n */\nconst DOWNGRADE_MAP: Record<Severity, Severity> = {\n critical: 'medium',\n high: 'low',\n medium: 'info',\n low: 'info',\n info: 'info',\n};\n\n/**\n * Rule IDs and matched patterns that are expected (not suspicious) for each category.\n * When a finding matches, its severity is downgraded.\n */\ninterface ExpectedBehavior {\n ruleIds?: string[];\n matchedPatterns?: string[];\n categories?: string[];\n}\n\n/**\n * For each extension category, define which rule findings are considered\n * expected/legitimate behavior and should be downgraded.\n */\nconst EXPECTED_BEHAVIORS: Partial<Record<ExtensionCategory, ExpectedBehavior[]>> = {\n 'ai-assistant': [\n {\n // AI tools legitimately use child_process, eval for code execution\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n 'eval',\n 'Function-constructor',\n 'dynamic-require',\n ],\n },\n {\n // AI tools legitimately make network requests\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['dynamic-url', 'unusual-port'],\n },\n {\n // AI tools often read .env for API keys\n ruleIds: ['EG-CRIT-003'],\n matchedPatterns: ['env-file'],\n },\n {\n // AI tools collect system info for telemetry / model context\n // This includes os.hostname, os.platform, os.userInfo, process.env, etc.\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // AI tools may have obfuscated/minified bundled code\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n\n theme: [\n {\n // Theme extensions with bundled JS may trigger obfuscation (false positive)\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n\n language: [\n {\n // Grammar extensions often have high-entropy bundled code or regex-heavy files\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n {\n // Grammar files use words like \"token\", \"secret\" in syntax definitions\n ruleIds: ['EG-HIGH-006'],\n matchedPatterns: ['generic-secret'],\n },\n ],\n\n scm: [\n {\n // SCM extensions legitimately access git credentials\n ruleIds: ['EG-CRIT-003'],\n matchedPatterns: ['git-credentials'],\n },\n {\n // SCM extensions may spawn git processes\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n ],\n },\n ],\n\n debugger: [\n {\n // Debuggers legitimately spawn processes\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n ],\n },\n {\n // Debuggers may use dynamic require for adapter loading\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: ['dynamic-require'],\n },\n ],\n\n linter: [\n {\n // Linters legitimately spawn processes (eslint, prettier, etc.)\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n ],\n },\n ],\n\n 'language-support': [\n {\n // Language servers spawn interpreters/compilers (python, go, rustc, javac)\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n 'dynamic-require',\n ],\n },\n {\n // Language servers may collect system info for environment detection\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // Language servers may have bundled code with high entropy\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n {\n // Language servers may make network requests for package management\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['dynamic-url'],\n },\n ],\n\n 'developer-tools': [\n {\n // Code runners spawn processes to execute code (python, node, bash, etc.)\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n 'eval',\n 'Function-constructor',\n ],\n },\n {\n // REST clients, API testers make network requests by design\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['dynamic-url', 'http-to-ip', 'unusual-port'],\n },\n {\n // Live servers spawn HTTP servers on various ports\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['unusual-port'],\n },\n {\n // Developer tools may collect system info for environment detection\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // Developer tools may have bundled code with high entropy\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n\n 'remote-development': [\n {\n // Remote extensions spawn SSH, docker, WSL processes\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n ],\n },\n {\n // Remote extensions make network connections by design\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['dynamic-url', 'http-to-ip', 'unusual-port'],\n },\n {\n // Remote extensions collect system info for environment detection\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // Remote extensions may access SSH keys and credentials legitimately\n ruleIds: ['EG-CRIT-003'],\n matchedPatterns: ['ssh-keys', 'ssh-config'],\n },\n {\n // Remote extensions may have bundled code\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n\n testing: [\n {\n // Test runners spawn test processes\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n ],\n },\n {\n // Test runners may collect system info for environment detection\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // Test runners may have bundled code\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n\n notebook: [\n {\n // Notebook extensions spawn kernels (Python, Julia, etc.)\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n 'dynamic-require',\n ],\n },\n {\n // Notebook extensions make network connections for package management\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['dynamic-url', 'unusual-port'],\n },\n {\n // Notebook extensions collect system info for environment detection\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // Notebook extensions may read environment files for kernel config\n ruleIds: ['EG-CRIT-003'],\n matchedPatterns: ['env-file'],\n },\n {\n // Notebook extensions may have bundled code\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n};\n\n/**\n * Check if a finding matches an expected behavior definition.\n */\nfunction matchesExpectedBehavior(finding: Finding, behavior: ExpectedBehavior): boolean {\n // Must match rule ID if specified\n if (behavior.ruleIds && !behavior.ruleIds.includes(finding.ruleId)) {\n return false;\n }\n\n // If matchedPatterns specified, the finding's evidence must match one\n if (behavior.matchedPatterns && behavior.matchedPatterns.length > 0) {\n const pattern = finding.evidence.matchedPattern ?? '';\n if (!behavior.matchedPatterns.some((p) => pattern.includes(p))) {\n return false;\n }\n }\n\n // If categories specified, the finding's category must match\n if (behavior.categories && behavior.categories.length > 0) {\n if (!behavior.categories.includes(finding.category)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Options for adjusting findings.\n */\nexport interface AdjustFindingsOptions {\n /** Publisher name for soft trust check */\n publisher?: string;\n /** Full extension ID (publisher.name) for soft trust check */\n extensionId?: string;\n /** Skip soft trust adjustments (strict mode) */\n strictMode?: boolean;\n /** Map of file paths to file contents for bundle detection */\n files?: Map<string, string>;\n}\n\n/**\n * Two-level downgrade map (for mega popular extensions)\n */\nconst DOUBLE_DOWNGRADE_MAP: Record<Severity, Severity> = {\n critical: 'low',\n high: 'info',\n medium: 'info',\n low: 'info',\n info: 'info',\n};\n\n/**\n * Adjust findings based on the extension's inferred category and trust status.\n *\n * Four layers of adjustment:\n * 1. Category-based: Expected behaviors for extension type (e.g., AI tools use network)\n * 2. Soft Trust: Trusted publishers get an additional severity downgrade\n * 3. Verified Publisher: Verified publishers on marketplace get severity downgrade\n * 4. Popularity: Extensions with 10M+ downloads get double downgrade, 1M+ get single\n *\n * Returns a new array with adjusted findings (original array is not mutated).\n */\nexport function adjustFindings(\n findings: Finding[],\n category: ExtensionCategory,\n options: AdjustFindingsOptions = {}\n): Finding[] {\n const { publisher, extensionId, strictMode = false } = options;\n const behaviors = EXPECTED_BEHAVIORS[category];\n\n // Check trust levels (only if not in strict mode)\n const isTrusted =\n !strictMode &&\n ((publisher && isTrustedPublisher(publisher)) ||\n (extensionId && isTrustedExtension(extensionId)));\n\n const isVerified = !strictMode && publisher && isVerifiedPublisher(publisher);\n\n const popularityTier = !strictMode && extensionId ? getPopularityTier(extensionId) : null;\n\n return findings.map((finding) => {\n let adjustedFinding = finding;\n let reasons: string[] = [];\n\n // Layer 1: Category-based adjustment\n if (behaviors && behaviors.length > 0) {\n for (const behavior of behaviors) {\n if (matchesExpectedBehavior(finding, behavior)) {\n const downgraded = DOWNGRADE_MAP[adjustedFinding.severity];\n adjustedFinding = {\n ...adjustedFinding,\n severity: downgraded,\n };\n reasons.push(`expected behavior for ${category} extension`);\n break;\n }\n }\n }\n\n // Layer 2: Soft Trust adjustment (additional downgrade for trusted publishers)\n if (isTrusted && adjustedFinding.severity !== 'info') {\n const downgraded = DOWNGRADE_MAP[adjustedFinding.severity];\n adjustedFinding = {\n ...adjustedFinding,\n severity: downgraded,\n };\n reasons.push(`trusted publisher`);\n }\n\n // Layer 3: Verified Publisher adjustment (if not already trusted)\n if (!isTrusted && isVerified && adjustedFinding.severity !== 'info') {\n const downgraded = DOWNGRADE_MAP[adjustedFinding.severity];\n adjustedFinding = {\n ...adjustedFinding,\n severity: downgraded,\n };\n reasons.push(`verified publisher`);\n }\n\n // Layer 4: Popularity-based adjustment\n if (popularityTier && adjustedFinding.severity !== 'info') {\n if (popularityTier === 'mega') {\n // 10M+ downloads: double downgrade\n const downgraded = DOUBLE_DOWNGRADE_MAP[adjustedFinding.severity];\n adjustedFinding = {\n ...adjustedFinding,\n severity: downgraded,\n };\n reasons.push(`mega popular (10M+ downloads)`);\n } else if (popularityTier === 'popular') {\n // 1M+ downloads: single downgrade\n const downgraded = DOWNGRADE_MAP[adjustedFinding.severity];\n adjustedFinding = {\n ...adjustedFinding,\n severity: downgraded,\n };\n reasons.push(`popular (1M+ downloads)`);\n }\n }\n\n // Add reason to description if any adjustments were made\n if (reasons.length > 0) {\n adjustedFinding = {\n ...adjustedFinding,\n description: `${finding.description} [Downgraded: ${reasons.join(' + ')}]`,\n };\n }\n\n return adjustedFinding;\n });\n}\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\nconst SYSTEM_INFO_PATTERNS = [\n { name: 'os.hostname', pattern: /os\\.hostname\\s*\\(\\)/g },\n { name: 'os.userInfo', pattern: /os\\.userInfo\\s*\\(\\)/g },\n { name: 'os.platform', pattern: /os\\.platform\\s*\\(\\)/g },\n { name: 'os.arch', pattern: /os\\.arch\\s*\\(\\)/g },\n { name: 'os.networkInterfaces', pattern: /os\\.networkInterfaces\\s*\\(\\)/g },\n { name: 'os.cpus', pattern: /os\\.cpus\\s*\\(\\)/g },\n { name: 'os.homedir', pattern: /os\\.homedir\\s*\\(\\)/g },\n { name: 'process.env', pattern: /process\\.env(?:\\[|\\.)/g },\n];\n\nconst HTTP_TO_IP_PATTERN =\n /(?:https?\\.request|fetch|axios\\.(?:get|post|put|request))\\s*\\(\\s*['\"`]https?:\\/\\/\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/g;\n\nexport const critDataExfiltration: DetectionRule = {\n id: 'EG-CRIT-001',\n name: 'Data Exfiltration Pattern',\n description:\n 'Detects code that collects system info and sends it to external servers via IP address',\n severity: 'critical',\n category: 'data-exfiltration',\n mitreAttackId: 'T1041',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const lines = content.split('\\n');\n\n // Check for system info collection\n let hasSystemInfo = false;\n let systemInfoPatternName = '';\n let systemInfoLine = 0;\n\n for (const { name, pattern } of SYSTEM_INFO_PATTERNS) {\n pattern.lastIndex = 0;\n const match = pattern.exec(content);\n if (match) {\n hasSystemInfo = true;\n systemInfoPatternName = name;\n systemInfoLine = content.slice(0, match.index).split('\\n').length;\n break;\n }\n }\n\n // Check for HTTP to IP\n HTTP_TO_IP_PATTERN.lastIndex = 0;\n const httpMatch = HTTP_TO_IP_PATTERN.exec(content);\n\n if (hasSystemInfo && httpMatch) {\n const httpToIpLine = content.slice(0, httpMatch.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber: httpToIpLine,\n lineContent: lines[httpToIpLine - 1]?.trim(),\n matchedPattern: `${systemInfoPatternName} + http-to-ip`,\n snippet: `System info (${systemInfoPatternName}) collected at line ${systemInfoLine}, sent to IP at line ${httpToIpLine}`,\n });\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\nconst DANGEROUS_PATTERNS = [\n { name: 'eval', pattern: /\\beval\\s*\\(/g },\n { name: 'Function-constructor', pattern: /new\\s+Function\\s*\\(/g },\n {\n name: 'child_process-exec',\n pattern: /(?:require\\s*\\(\\s*['\"]child_process['\"]\\s*\\)|child_process)\\.exec\\s*\\(/g,\n },\n {\n name: 'child_process-execSync',\n pattern: /(?:require\\s*\\(\\s*['\"]child_process['\"]\\s*\\)|child_process)\\.execSync\\s*\\(/g,\n },\n { name: 'child_process-spawn-shell', pattern: /\\.spawn\\s*\\([^)]*\\{[^}]*shell\\s*:\\s*true/g },\n { name: 'vm-runInContext', pattern: /vm\\.run(?:InContext|InNewContext|InThisContext)\\s*\\(/g },\n { name: 'vm-Script', pattern: /new\\s+vm\\.Script\\s*\\(/g },\n];\n\nconst DYNAMIC_REQUIRE = /require\\s*\\(\\s*(?:[^'\"`\\s)]|`[^`]*\\$\\{)/g;\n\nexport const critRemoteExecution: DetectionRule = {\n id: 'EG-CRIT-002',\n name: 'Remote Code Execution',\n description: 'Detects dangerous code execution patterns like eval, exec, or dynamic require',\n severity: 'critical',\n category: 'remote-code-execution',\n mitreAttackId: 'T1059',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const lines = content.split('\\n');\n\n for (const { name, pattern } of DANGEROUS_PATTERNS) {\n pattern.lastIndex = 0;\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lines[lineNumber - 1]?.trim(),\n matchedPattern: name,\n snippet: match[0],\n });\n }\n }\n\n DYNAMIC_REQUIRE.lastIndex = 0;\n let match;\n while ((match = DYNAMIC_REQUIRE.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lines[lineNumber - 1]?.trim(),\n matchedPattern: 'dynamic-require',\n snippet: match[0],\n });\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\nconst SENSITIVE_PATHS = [\n {\n name: 'ssh-keys',\n pattern:\n /['\"`][^'\"`]*\\.ssh[/\\\\](?:id_rsa|id_ed25519|id_ecdsa|known_hosts|config|authorized_keys)[^'\"`]*['\"`]/gi,\n },\n { name: 'gnupg', pattern: /['\"`][^'\"`]*\\.gnupg[/\\\\][^'\"`]*['\"`]/gi },\n { name: 'aws-credentials', pattern: /['\"`][^'\"`]*\\.aws[/\\\\]credentials[^'\"`]*['\"`]/gi },\n { name: 'azure-config', pattern: /['\"`][^'\"`]*\\.azure[/\\\\][^'\"`]*['\"`]/gi },\n { name: 'kube-config', pattern: /['\"`][^'\"`]*\\.kube[/\\\\]config[^'\"`]*['\"`]/gi },\n { name: 'git-credentials', pattern: /['\"`][^'\"`]*\\.git-credentials[^'\"`]*['\"`]/gi },\n { name: 'env-file', pattern: /['\"`][^'\"`]*\\.env(?:\\.\\w+)?['\"`]/gi },\n { name: 'npmrc', pattern: /['\"`][^'\"`]*\\.npmrc[^'\"`]*['\"`]/gi },\n { name: 'docker-config', pattern: /['\"`][^'\"`]*\\.docker[/\\\\]config\\.json[^'\"`]*['\"`]/gi },\n { name: 'netrc', pattern: /['\"`][^'\"`]*\\.netrc[^'\"`]*['\"`]/gi },\n];\n\nconst FILE_READ_CONTEXT =\n /(?:readFile|readFileSync|createReadStream|access|accessSync|exists|existsSync|stat|statSync|open|openSync)/;\n\nexport const critCredentialAccess: DetectionRule = {\n id: 'EG-CRIT-003',\n name: 'Credential File Access',\n description:\n 'Detects attempts to read sensitive credential files like SSH keys, AWS credentials, or .env files',\n severity: 'critical',\n category: 'credential-theft',\n mitreAttackId: 'T1552.004',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const lines = content.split('\\n');\n\n for (const { name, pattern } of SENSITIVE_PATHS) {\n pattern.lastIndex = 0;\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const startIndex = Math.max(0, match.index - 200);\n const endIndex = Math.min(content.length, match.index + match[0].length + 200);\n const context = content.slice(startIndex, endIndex);\n\n if (FILE_READ_CONTEXT.test(context)) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lines[lineNumber - 1]?.trim(),\n matchedPattern: name,\n snippet: match[0],\n });\n }\n }\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\n// HTTP requests to IP addresses instead of domains\nconst HTTP_TO_IP =\n /(?:fetch|axios(?:\\.(?:get|post|put|delete|request))?|https?\\.(?:get|post|request)|XMLHttpRequest)\\s*\\([^)]*['\"`]https?:\\/\\/\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/g;\n\n// Dynamic URL construction (template literals or concatenation)\nconst DYNAMIC_URL =\n /(?:fetch|axios|https?\\.request)\\s*\\(\\s*(?:`[^`]*\\$\\{|['\"][^'\"]*['\"]\\s*\\+\\s*\\w)/g;\n\n// WebSocket connections to IP addresses\nconst WEBSOCKET_TO_IP = /new\\s+WebSocket\\s*\\(\\s*['\"`]wss?:\\/\\/\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/g;\n\n// Unusual ports\nconst UNUSUAL_PORTS = /['\"`]https?:\\/\\/[^'\"`:]+:(?!443|80|8080|3000|8443|5000)[0-9]{2,5}/g;\n\nexport const highSuspiciousNetwork: DetectionRule = {\n id: 'EG-HIGH-002',\n name: 'Suspicious Network Activity',\n description: 'Detects network requests to IP addresses, dynamic URLs, or unusual ports',\n severity: 'high',\n category: 'suspicious-network',\n mitreAttackId: 'T1071',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const lines = content.split('\\n');\n const patterns = [\n { pattern: HTTP_TO_IP, name: 'http-to-ip' },\n { pattern: DYNAMIC_URL, name: 'dynamic-url' },\n { pattern: WEBSOCKET_TO_IP, name: 'websocket-to-ip' },\n { pattern: UNUSUAL_PORTS, name: 'unusual-port' },\n ];\n\n for (const { pattern, name } of patterns) {\n pattern.lastIndex = 0;\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lines[lineNumber - 1]?.trim(),\n matchedPattern: name,\n snippet: match[0].slice(0, 100),\n });\n }\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\nconst MIN_BASE64_LENGTH = 100;\nconst BASE64_PATTERN = /['\"`]([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?['\"`]/g;\nconst HEX_PATTERN = /(?:\\\\x[0-9a-fA-F]{2}){10,}/g;\nconst CHAR_CODE_PATTERN = /String\\.fromCharCode\\s*\\(\\s*(?:\\d+\\s*,?\\s*){5,}\\)/g;\nconst UNICODE_ESCAPE_PATTERN = /(?:\\\\u[0-9a-fA-F]{4}){10,}/g;\n\n// Bundled/minified files: single large JS in dist/ or out/ directory, or well-known bundler output\nconst BUNDLED_FILE_PATTERN = /(?:^|\\/)(?:dist|out|build|bundle)\\//;\nconst BUNDLED_FILE_SIZE_THRESHOLD = 100 * 1024; // 100KB — typical bundle size\n\nfunction calculateEntropy(str: string): number {\n const len = str.length;\n if (len === 0) return 0;\n const freq: Record<string, number> = {};\n for (const char of str) {\n freq[char] = (freq[char] || 0) + 1;\n }\n let entropy = 0;\n for (const count of Object.values(freq)) {\n const p = count / len;\n entropy -= p * Math.log2(p);\n }\n return entropy;\n}\n\nexport const highObfuscatedCode: DetectionRule = {\n id: 'EG-HIGH-001',\n name: 'Code Obfuscation Detected',\n description: 'Detects heavily obfuscated code patterns that may hide malicious behavior',\n severity: 'high',\n category: 'code-obfuscation',\n mitreAttackId: 'T1027',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const lines = content.split('\\n');\n\n // Check for large base64 strings\n BASE64_PATTERN.lastIndex = 0;\n let match;\n while ((match = BASE64_PATTERN.exec(content)) !== null) {\n const base64Content = match[0].slice(1, -1);\n if (base64Content.length >= MIN_BASE64_LENGTH) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: (lines[lineNumber - 1]?.trim() || '').slice(0, 80) + '...',\n matchedPattern: 'large-base64',\n snippet: `Base64 string of ${base64Content.length} characters`,\n });\n }\n }\n\n // Check for hex-encoded strings\n HEX_PATTERN.lastIndex = 0;\n while ((match = HEX_PATTERN.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: (lines[lineNumber - 1]?.trim() || '').slice(0, 80) + '...',\n matchedPattern: 'hex-encoded',\n snippet: match[0].slice(0, 50) + '...',\n });\n }\n\n // Check for String.fromCharCode abuse\n CHAR_CODE_PATTERN.lastIndex = 0;\n while ((match = CHAR_CODE_PATTERN.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lines[lineNumber - 1]?.trim(),\n matchedPattern: 'charcode-obfuscation',\n snippet: match[0].slice(0, 80),\n });\n }\n\n // Check for unicode escape sequences\n UNICODE_ESCAPE_PATTERN.lastIndex = 0;\n while ((match = UNICODE_ESCAPE_PATTERN.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: (lines[lineNumber - 1]?.trim() || '').slice(0, 80) + '...',\n matchedPattern: 'unicode-escape',\n snippet: match[0].slice(0, 50) + '...',\n });\n }\n\n // Check overall file entropy for large files\n // Skip bundled/minified files (>100KB in dist/out/build dirs) — they naturally have high entropy\n const isBundled =\n BUNDLED_FILE_PATTERN.test(filePath) && content.length > BUNDLED_FILE_SIZE_THRESHOLD;\n\n if (!isBundled && content.length > 5000) {\n const entropy = calculateEntropy(content);\n // Threshold raised from 5.8 to 6.2 — bundled JS with regex-heavy content\n // (grammar definitions, URL patterns) routinely hits 5.8-6.0\n if (entropy > 6.2) {\n evidences.push({\n filePath,\n lineNumber: 1,\n matchedPattern: 'high-entropy',\n snippet: `File entropy: ${entropy.toFixed(2)} (threshold: 6.2)`,\n });\n }\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\n// Minimum length for a value to be considered a potential secret\nconst MIN_SECRET_LENGTH = 8;\n\n// Minimum entropy for generic-secret values — filters out natural language and config values\nconst MIN_GENERIC_SECRET_ENTROPY = 3.0;\n\n// Patterns that indicate placeholder values (false positives)\nconst PLACEHOLDER_PATTERNS = [\n /^your[_-]?/i,\n /^<[^>]+>$/,\n /^replace[_-]?me$/i,\n /^xxx+$/i,\n /^x{3,}[_-]x{3,}/i,\n /^todo$/i,\n /^fixme$/i,\n /^example$/i,\n /^placeholder$/i,\n /^changeme$/i,\n /^\\*+$/,\n /^\\.+$/,\n /^test$/i,\n /^demo$/i,\n];\n\n// Common false-positive values for generic-secret pattern\n// These are legitimate config/code patterns, not actual secrets\nconst FALSE_POSITIVE_VALUES = [\n /^(?:true|false|null|undefined|none)$/i,\n /^(?:string|number|boolean|object|array|function)$/i,\n /^(?:keyword|identifier|operator|punctuation|comment|variable|constant)$/i, // TextMate token types\n /^(?:bearer|basic|digest)\\s/i, // Auth scheme names, not actual tokens\n /^(?:process\\.env|os\\.environ)/i, // Env access patterns\n /^https?:\\/\\//i, // URLs\n /^\\$\\{/, // Template literals\n /^%[sd]/, // Format strings\n];\n\n// File patterns to exclude (test files, examples, docs)\nconst EXCLUDED_FILE_PATTERNS = [\n /\\.test\\.[jt]sx?$/,\n /\\.spec\\.[jt]sx?$/,\n /__tests__\\//,\n /(?:^|\\/)test\\//,\n /(?:^|\\/)tests\\//,\n /(?:^|\\/)examples?\\//,\n /(?:^|\\/)demo\\//,\n /\\.md$/,\n /\\.txt$/,\n /\\.rst$/,\n];\n\n// Code file extensions to scan\nconst CODE_FILE_EXTENSIONS = ['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs'];\n\ninterface SecretPattern {\n name: string;\n pattern: RegExp;\n matchGroup?: number;\n}\n\nconst SECRET_PATTERNS: SecretPattern[] = [\n // AWS Access Key ID (starts with AKIA)\n {\n name: 'aws-access-key',\n pattern: /AKIA[0-9A-Z]{16}/g,\n },\n // AWS Secret Access Key\n {\n name: 'aws-secret-key',\n pattern:\n /(?:aws[_-]?secret(?:[_-]?access)?[_-]?key|secret[_-]?access[_-]?key)\\s*[:=]\\s*['\"`]([A-Za-z0-9/+=]{40})['\"`]/gi,\n matchGroup: 1,\n },\n // GitHub tokens (ghp_, gho_, ghs_, ghr_)\n {\n name: 'github-token',\n pattern: /gh[pors]_[A-Za-z0-9]{36,}/g,\n },\n // Slack tokens (xoxb-, xoxp-, xoxa-, xoxr-)\n {\n name: 'slack-token',\n pattern: /xox[bpar]-[0-9]+-[0-9]+-[A-Za-z0-9]+/g,\n },\n // Private keys\n {\n name: 'private-key',\n pattern: /-----BEGIN\\s+(?:RSA\\s+|EC\\s+|DSA\\s+|OPENSSH\\s+)?PRIVATE\\s+KEY-----/g,\n },\n // Bearer tokens (JWT format)\n {\n name: 'bearer-token',\n pattern: /Bearer\\s+([A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+)/g,\n matchGroup: 1,\n },\n // API key assignments\n {\n name: 'api-key',\n pattern: /(?:api[_-]?key|apikey)\\s*[:=]\\s*['\"`]([A-Za-z0-9_-]{16,})['\"`]/gi,\n matchGroup: 1,\n },\n // Generic secrets (password, secret, token, passwd, pwd)\n {\n name: 'generic-secret',\n pattern: /(?:password|passwd|pwd|secret|token)\\s*[:=]\\s*['\"`]([^'\"`]{8,})['\"`]/gi,\n matchGroup: 1,\n },\n];\n\nfunction isCodeFile(filePath: string): boolean {\n return CODE_FILE_EXTENSIONS.some((ext) => filePath.endsWith(ext));\n}\n\nfunction isExcludedFile(filePath: string): boolean {\n return EXCLUDED_FILE_PATTERNS.some((pattern) => pattern.test(filePath));\n}\n\nfunction isPlaceholder(value: string): boolean {\n return PLACEHOLDER_PATTERNS.some((pattern) => pattern.test(value));\n}\n\nfunction isFalsePositiveValue(value: string): boolean {\n return FALSE_POSITIVE_VALUES.some((pattern) => pattern.test(value));\n}\n\nfunction calculateSecretEntropy(str: string): number {\n const len = str.length;\n if (len === 0) return 0;\n const freq: Record<string, number> = {};\n for (const char of str) {\n freq[char] = (freq[char] || 0) + 1;\n }\n let entropy = 0;\n for (const count of Object.values(freq)) {\n const p = count / len;\n entropy -= p * Math.log2(p);\n }\n return entropy;\n}\n\nfunction isInComment(content: string, matchIndex: number): boolean {\n // Find the start of the line containing the match\n const lineStart = content.lastIndexOf('\\n', matchIndex) + 1;\n const lineContent = content.slice(lineStart, matchIndex);\n\n // Check for single-line comment\n if (lineContent.includes('//')) {\n return true;\n }\n\n // Check for block comment - look for /* before the match without a closing */\n const beforeMatch = content.slice(0, matchIndex);\n const lastBlockStart = beforeMatch.lastIndexOf('/*');\n const lastBlockEnd = beforeMatch.lastIndexOf('*/');\n\n if (lastBlockStart > lastBlockEnd) {\n return true;\n }\n\n return false;\n}\n\nfunction getLineNumber(content: string, index: number): number {\n return content.slice(0, index).split('\\n').length;\n}\n\nexport const highHardcodedSecret: DetectionRule = {\n id: 'EG-HIGH-006',\n name: 'Hardcoded Secrets',\n description: 'Detects hardcoded API keys, tokens, passwords, and other secrets in code',\n severity: 'high',\n category: 'hardcoded-secret',\n mitreAttackId: 'T1552.001',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n // Skip non-code files\n if (!isCodeFile(filePath)) {\n continue;\n }\n\n // Skip test/example files\n if (isExcludedFile(filePath)) {\n continue;\n }\n\n // Skip empty files\n if (!content || content.trim().length === 0) {\n continue;\n }\n\n const lines = content.split('\\n');\n\n for (const secretPattern of SECRET_PATTERNS) {\n // Reset regex lastIndex to avoid issues with global flag\n secretPattern.pattern.lastIndex = 0;\n\n let match;\n while ((match = secretPattern.pattern.exec(content)) !== null) {\n const matchIndex = match.index;\n\n // Skip if in a comment\n if (isInComment(content, matchIndex)) {\n continue;\n }\n\n // Get the actual secret value (either from capture group or full match)\n const secretValue =\n secretPattern.matchGroup !== undefined ? match[secretPattern.matchGroup] : match[0];\n\n // Skip if no secret value found\n if (!secretValue) {\n continue;\n }\n\n // Skip short values for generic patterns\n if (secretPattern.name === 'generic-secret' && secretValue.length < MIN_SECRET_LENGTH) {\n continue;\n }\n\n // Skip placeholder values\n if (isPlaceholder(secretValue)) {\n continue;\n }\n\n // Skip known false-positive values\n if (isFalsePositiveValue(secretValue)) {\n continue;\n }\n\n // For generic-secret, require minimum entropy to filter out\n // natural language config values like tokenType = \"keyword\"\n if (secretPattern.name === 'generic-secret') {\n const entropy = calculateSecretEntropy(secretValue);\n if (entropy < MIN_GENERIC_SECRET_ENTROPY) {\n continue;\n }\n }\n\n const lineNumber = getLineNumber(content, matchIndex);\n const lineContent = lines[lineNumber - 1]?.trim() || '';\n\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lineContent.length > 100 ? lineContent.slice(0, 100) + '...' : lineContent,\n matchedPattern: secretPattern.name,\n snippet: `Detected ${secretPattern.name}: ${secretValue.slice(0, 20)}${secretValue.length > 20 ? '...' : ''}`,\n });\n }\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\nexport const medExcessiveActivation: DetectionRule = {\n id: 'EG-MED-001',\n name: 'Excessive Activation Events',\n description:\n 'Extension uses \"*\" activation event which means it activates on every action, potentially for surveillance',\n severity: 'medium',\n category: 'excessive-permission',\n enabled: true,\n\n detect(_files: Map<string, string>, manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n const activationEvents = manifest.activationEvents ?? [];\n\n // Check for \"*\" activation event\n if (activationEvents.includes('*')) {\n evidences.push({\n filePath: 'package.json',\n lineNumber: 1,\n matchedPattern: 'activation-star',\n snippet: 'activationEvents: [\"*\"]',\n lineContent: 'Extension activates on every VS Code action',\n });\n }\n\n // Check for onStartupFinished (runs immediately after VS Code starts)\n if (activationEvents.includes('onStartupFinished')) {\n evidences.push({\n filePath: 'package.json',\n lineNumber: 1,\n matchedPattern: 'activation-startup',\n snippet: 'activationEvents: [\"onStartupFinished\"]',\n lineContent: 'Extension activates immediately on VS Code startup',\n });\n }\n\n return evidences;\n },\n};\n","import { ruleRegistry } from '../rule-registry.js';\nimport { critDataExfiltration } from './crit-data-exfiltration.js';\nimport { critRemoteExecution } from './crit-remote-execution.js';\nimport { critCredentialAccess } from './crit-credential-access.js';\nimport { highSuspiciousNetwork } from './high-suspicious-network.js';\nimport { highObfuscatedCode } from './high-obfuscated-code.js';\nimport { highHardcodedSecret } from './high-hardcoded-secret.js';\nimport { medExcessiveActivation } from './med-excessive-activation.js';\n\nexport function registerBuiltInRules(): void {\n ruleRegistry.register(critDataExfiltration);\n ruleRegistry.register(critRemoteExecution);\n ruleRegistry.register(critCredentialAccess);\n ruleRegistry.register(highSuspiciousNetwork);\n ruleRegistry.register(highObfuscatedCode);\n ruleRegistry.register(highHardcodedSecret);\n ruleRegistry.register(medExcessiveActivation);\n}\n\nexport {\n critDataExfiltration,\n critRemoteExecution,\n critCredentialAccess,\n highSuspiciousNetwork,\n highObfuscatedCode,\n highHardcodedSecret,\n medExcessiveActivation,\n};\n\n/**\n * All built-in detection rules with their metadata.\n * Useful for CLI commands that list rules.\n */\nexport const DETECTION_RULES = [\n critDataExfiltration,\n critRemoteExecution,\n critCredentialAccess,\n highSuspiciousNetwork,\n highObfuscatedCode,\n highHardcodedSecret,\n medExcessiveActivation,\n];\n","import type { ExtensionManifest } from '../types/index.js';\n\n/**\n * Inferred extension category used to adjust finding severity.\n * Extensions in different categories have different \"normal\" behaviors.\n */\nexport type ExtensionCategory =\n | 'theme' // Color themes, icon themes — should have zero runtime behavior\n | 'language' // Grammars, syntax highlighting, snippets — minimal runtime\n | 'ai-assistant' // AI coding tools — legitimately need network, process, env\n | 'scm' // Source control — may access git-credentials legitimately\n | 'debugger' // Debuggers — may spawn processes legitimately\n | 'linter' // Linters, formatters — may spawn processes\n | 'language-support' // Language servers, Python, Go, Rust — spawn interpreters/compilers\n | 'developer-tools' // Code runners, REST clients, live servers — spawn processes, network\n | 'remote-development' // Remote-SSH, Dev Containers, WSL — spawn processes, network\n | 'testing' // Test runners — spawn test processes\n | 'notebook' // Jupyter, notebooks — spawn kernels, network\n | 'general'; // Everything else\n\n/**\n * Publishers known to provide language support extensions (Python, Go, Rust, etc.)\n * These extensions legitimately spawn language servers and interpreters.\n */\nconst LANGUAGE_SUPPORT_PUBLISHERS = [\n 'ms-python',\n 'ms-vscode',\n 'golang',\n 'rust-lang',\n 'microsoft',\n 'redhat',\n 'oracle',\n 'julialang',\n 'haskell',\n // Additional language support publishers\n 'zigtools',\n 'elixir-lsp',\n 'dart-code',\n 'scala-lang',\n 'vscjava',\n 'crystal-lang-tools',\n 'nim-lang',\n 'vlang-vscode',\n];\n\n/**\n * Keywords to detect developer tool extensions (code runners, REST clients, live servers)\n * These extensions legitimately spawn processes and make network requests.\n */\nconst DEVELOPER_TOOL_KEYWORDS = [\n // Code execution\n 'code runner',\n 'coderunner',\n 'run code',\n 'execute code',\n 'run script',\n 'script runner',\n // REST/API clients\n 'rest client',\n 'api client',\n 'http client',\n 'thunder client',\n 'postman',\n 'insomnia',\n 'api tester',\n 'http request',\n // Live servers\n 'live server',\n 'liveserver',\n 'live preview',\n 'browser sync',\n 'browsersync',\n 'local server',\n 'dev server',\n 'http server',\n // Terminal/Shell\n 'terminal',\n 'shell',\n 'integrated terminal',\n // Task runners\n 'task runner',\n 'npm scripts',\n 'gulp',\n 'grunt',\n // Database clients\n 'database client',\n 'sql client',\n 'mongodb client',\n 'redis client',\n];\n\n/**\n * Publishers known to provide developer tools (code runners, REST clients, etc.)\n */\nconst DEVELOPER_TOOL_PUBLISHERS = [\n 'formulahendry', // Code Runner\n 'rangav', // Thunder Client\n 'humao', // REST Client\n 'ritwickdey', // Live Server\n 'techer', // Live Server (alternative)\n 'negokaz', // Live Server (alternative)\n 'qwtel', // HTTP/S Server\n 'hediet', // Debug Visualizer\n 'mtxr', // SQLTools\n 'cweijan', // Database Client\n];\n\n/**\n * Keywords to detect remote development extensions (SSH, containers, WSL)\n * These extensions legitimately spawn processes and make network connections.\n */\nconst REMOTE_DEV_KEYWORDS = [\n 'remote-ssh',\n 'remote ssh',\n 'remote - ssh',\n 'dev container',\n 'devcontainer',\n 'dev-container',\n 'docker container',\n 'wsl',\n 'windows subsystem',\n 'remote development',\n 'remote explorer',\n 'ssh remote',\n 'ssh connection',\n 'container development',\n 'codespace',\n 'github codespaces',\n 'tunnel',\n 'remote tunnels',\n];\n\n/**\n * Publishers known to provide remote development extensions.\n */\nconst REMOTE_DEV_PUBLISHERS = [\n 'ms-vscode-remote', // Remote-SSH, Dev Containers, WSL\n 'ms-azuretools', // Azure (containers, etc.)\n];\n\n/**\n * Keywords to detect testing extensions (test runners, test frameworks)\n * These extensions legitimately spawn test processes.\n */\nconst TESTING_KEYWORDS = [\n 'test runner',\n 'test explorer',\n 'test adapter',\n 'jest runner',\n 'mocha test',\n 'pytest',\n 'vitest',\n 'karma',\n 'jasmine',\n 'cypress',\n 'playwright',\n 'selenium',\n 'unit test',\n 'integration test',\n 'e2e test',\n 'end-to-end test',\n 'test coverage',\n 'code coverage',\n];\n\n/**\n * Publishers known to provide testing extensions.\n */\nconst TESTING_PUBLISHERS = [\n 'hbenl', // Test Explorer UI\n 'firsttris', // Jest Runner\n 'orta', // Jest (vscode-jest)\n 'ms-playwright', // Playwright\n];\n\n/**\n * Keywords to detect notebook extensions (Jupyter, etc.)\n * These extensions legitimately spawn kernels and make network requests.\n */\nconst NOTEBOOK_KEYWORDS = [\n 'jupyter',\n 'notebook',\n 'ipynb',\n 'kernel',\n 'jupyter notebook',\n 'jupyter lab',\n 'ipython',\n 'data science',\n 'interactive python',\n];\n\n/**\n * Publishers known to provide notebook extensions.\n */\nconst NOTEBOOK_PUBLISHERS = [\n 'ms-toolsai', // Jupyter\n];\n\nconst AI_KEYWORDS = [\n 'copilot',\n 'ai',\n 'gpt',\n 'llm',\n 'chatbot',\n 'assistant',\n 'autocomplete',\n 'code completion',\n 'machine learning',\n 'neural',\n 'openai',\n 'anthropic',\n 'gemini',\n 'claude',\n 'codeium',\n 'tabnine',\n 'kilo',\n 'continue',\n 'cursor',\n 'supermaven',\n // Additional AI tools\n 'aider',\n 'codestral',\n 'mistral',\n 'deepseek',\n 'qwen',\n 'sourcery',\n 'codewhisperer',\n 'amazon q',\n 'bito',\n 'blackbox',\n 'codegpt',\n 'cody', // Sourcegraph\n];\n\n/**\n * Infer an extension's category from its manifest (package.json).\n * Uses categories, contributes, keywords, displayName, and description.\n */\nexport function categorizeExtension(manifest: ExtensionManifest): ExtensionCategory {\n const categories = (manifest.categories ?? []).map((c) => c.toLowerCase());\n const contributes = manifest.contributes ?? {};\n const contributeKeys = Object.keys(contributes);\n const keywords = ((manifest as Record<string, unknown>).keywords as string[] | undefined) ?? [];\n const displayName = (manifest.displayName ?? '').toLowerCase();\n const description = (manifest.description ?? '').toLowerCase();\n const name = (manifest.name ?? '').toLowerCase();\n\n // Theme: explicit category or only contributes themes\n if (\n categories.includes('themes') ||\n categories.includes('icon themes') ||\n isThemeOnlyExtension(contributeKeys, contributes)\n ) {\n return 'theme';\n }\n\n // Language/Grammar: contributes grammars or languages with minimal other functionality\n if (isLanguageExtension(contributeKeys, contributes)) {\n return 'language';\n }\n\n // Remote development: SSH, containers, WSL\n // Must be checked BEFORE language-support (ms-vscode-remote contains ms-vscode)\n if (isRemoteDevelopment(manifest, displayName, description, name)) {\n return 'remote-development';\n }\n\n // AI assistant: check categories, keywords, name, description\n if (isAIAssistant(categories, keywords, displayName, description, name)) {\n return 'ai-assistant';\n }\n\n // Language support: extensions that run language servers, interpreters, compilers\n // Must be checked AFTER ai-assistant (some AI tools also have language support)\n if (isLanguageSupport(manifest, categories)) {\n return 'language-support';\n }\n\n // SCM\n if (categories.includes('scm providers') || contributeKeys.includes('scm')) {\n return 'scm';\n }\n\n // Debugger\n if (categories.includes('debuggers') || contributeKeys.includes('debuggers')) {\n return 'debugger';\n }\n\n // Linter / Formatter\n if (\n categories.includes('linters') ||\n categories.includes('formatters') ||\n displayName.includes('lint') ||\n displayName.includes('format') ||\n displayName.includes('prettier') ||\n displayName.includes('eslint')\n ) {\n return 'linter';\n }\n\n // Developer tools: code runners, REST clients, live servers\n if (isDeveloperTool(manifest, displayName, description, name)) {\n return 'developer-tools';\n }\n\n // Testing: test runners, test frameworks\n if (isTesting(manifest, categories, displayName, description, name)) {\n return 'testing';\n }\n\n // Notebook: Jupyter, ipynb\n if (isNotebook(manifest, categories, displayName, description, name, contributeKeys)) {\n return 'notebook';\n }\n\n return 'general';\n}\n\nfunction isThemeOnlyExtension(\n contributeKeys: string[],\n _contributes: Record<string, unknown>\n): boolean {\n const hasThemes = contributeKeys.includes('themes') || contributeKeys.includes('iconThemes');\n if (!hasThemes) return false;\n\n // If the extension ONLY contributes themes (no commands, no other functionality)\n const functionalKeys = contributeKeys.filter(\n (k) => k !== 'themes' && k !== 'iconThemes' && k !== 'colors'\n );\n return functionalKeys.length === 0;\n}\n\nfunction isLanguageExtension(\n contributeKeys: string[],\n contributes: Record<string, unknown>\n): boolean {\n const hasGrammars = contributeKeys.includes('grammars') || contributeKeys.includes('languages');\n if (!hasGrammars) return false;\n\n // Language extension if it contributes grammars/languages but not many commands\n const commands = contributes.commands;\n if (Array.isArray(commands) && commands.length > 3) {\n return false; // Too many commands — likely a full-featured extension\n }\n\n return true;\n}\n\nfunction isAIAssistant(\n categories: string[],\n keywords: string[],\n displayName: string,\n description: string,\n name: string\n): boolean {\n // Check explicit ML category\n if (categories.includes('machine learning') || categories.includes('data science')) {\n return true;\n }\n\n // Check keywords, displayName, description, name against AI keywords\n const searchableText = [\n ...keywords.map((k) => k.toLowerCase()),\n displayName,\n description,\n name,\n ].join(' ');\n\n // Use word boundary matching to avoid false positives like \"continue\" matching \"container\"\n return AI_KEYWORDS.some((kw) => {\n // For multi-word keywords, use simple includes\n if (kw.includes(' ')) {\n return searchableText.includes(kw);\n }\n // For single-word keywords, use word boundary regex\n const regex = new RegExp(`\\\\b${kw}\\\\b`, 'i');\n return regex.test(searchableText);\n });\n}\n\n/**\n * Detect language support extensions (Python, Go, Rust, Java, C++, etc.)\n * These extensions need to spawn language servers and interpreters.\n */\nfunction isLanguageSupport(manifest: ExtensionManifest, categories: string[]): boolean {\n const publisher = (manifest.publisher ?? '').toLowerCase();\n\n // Check known language support publishers\n if (LANGUAGE_SUPPORT_PUBLISHERS.some((p) => publisher.includes(p))) {\n return true;\n }\n\n // Check for \"Programming Languages\" category\n if (categories.includes('programming languages')) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Detect developer tool extensions (code runners, REST clients, live servers, etc.)\n * These extensions legitimately spawn processes and make network requests.\n */\nfunction isDeveloperTool(\n manifest: ExtensionManifest,\n displayName: string,\n description: string,\n name: string\n): boolean {\n const publisher = (manifest.publisher ?? '').toLowerCase();\n\n // Check known developer tool publishers\n if (DEVELOPER_TOOL_PUBLISHERS.some((p) => publisher === p)) {\n return true;\n }\n\n // Check displayName, description, name against developer tool keywords\n const searchableText = [displayName, description, name].join(' ');\n\n return DEVELOPER_TOOL_KEYWORDS.some((kw) => searchableText.includes(kw));\n}\n\n/**\n * Detect remote development extensions (SSH, containers, WSL, etc.)\n * These extensions legitimately spawn processes and make network connections.\n */\nfunction isRemoteDevelopment(\n manifest: ExtensionManifest,\n displayName: string,\n description: string,\n name: string\n): boolean {\n const publisher = (manifest.publisher ?? '').toLowerCase();\n\n // Check known remote development publishers\n if (REMOTE_DEV_PUBLISHERS.some((p) => publisher === p)) {\n return true;\n }\n\n // Check displayName, description, name against remote development keywords\n const searchableText = [displayName, description, name].join(' ');\n\n return REMOTE_DEV_KEYWORDS.some((kw) => searchableText.includes(kw));\n}\n\n/**\n * Detect testing extensions (test runners, test frameworks, etc.)\n * These extensions legitimately spawn test processes.\n */\nfunction isTesting(\n manifest: ExtensionManifest,\n categories: string[],\n displayName: string,\n description: string,\n name: string\n): boolean {\n const publisher = (manifest.publisher ?? '').toLowerCase();\n\n // Check known testing publishers\n if (TESTING_PUBLISHERS.some((p) => publisher === p)) {\n return true;\n }\n\n // Check for \"Testing\" category\n if (categories.includes('testing')) {\n return true;\n }\n\n // Check displayName, description, name against testing keywords\n const searchableText = [displayName, description, name].join(' ');\n\n return TESTING_KEYWORDS.some((kw) => searchableText.includes(kw));\n}\n\n/**\n * Detect notebook extensions (Jupyter, etc.)\n * These extensions legitimately spawn kernels and make network requests.\n */\nfunction isNotebook(\n manifest: ExtensionManifest,\n categories: string[],\n displayName: string,\n description: string,\n name: string,\n contributeKeys: string[]\n): boolean {\n const publisher = (manifest.publisher ?? '').toLowerCase();\n\n // Check known notebook publishers\n if (NOTEBOOK_PUBLISHERS.some((p) => publisher === p)) {\n return true;\n }\n\n // Check for \"Notebooks\" category\n if (categories.includes('notebooks')) {\n return true;\n }\n\n // Check if contributes notebooks\n if (contributeKeys.includes('notebooks') || contributeKeys.includes('notebookRenderer')) {\n return true;\n }\n\n // Check displayName, description, name against notebook keywords\n const searchableText = [displayName, description, name].join(' ');\n\n return NOTEBOOK_KEYWORDS.some((kw) => searchableText.includes(kw));\n}\n","/**\n * Extension Integrity Verifier\n *\n * Verifies that installed extensions match their known-good hashes.\n * This detects supply chain attacks where an official extension has been\n * tampered with after installation or during distribution.\n *\n * Verification methods:\n * 1. File content hash - SHA256 of all JS files concatenated\n * 2. Manifest hash - SHA256 of package.json\n * 3. Structure hash - Hash of file list (detects added/removed files)\n */\n\nimport { createHash } from 'node:crypto';\n\n/**\n * Hash record for a specific extension version\n */\nexport interface ExtensionHash {\n /** Extension ID (publisher.name) */\n extensionId: string;\n /** Version string */\n version: string;\n /** SHA256 of package.json content */\n manifestHash: string;\n /** SHA256 of all JS file contents concatenated (sorted by path) */\n contentHash: string;\n /** SHA256 of sorted file path list */\n structureHash: string;\n /** Combined hash for quick comparison */\n combinedHash: string;\n /** When this hash was recorded */\n recordedAt: string;\n /** Source of the hash (marketplace, manual, etc.) */\n source: 'marketplace' | 'manual' | 'community';\n}\n\n/**\n * Result of integrity verification\n */\nexport interface IntegrityResult {\n extensionId: string;\n version: string;\n status: 'verified' | 'modified' | 'unknown' | 'error';\n /** Which parts were modified (if status is 'modified') */\n modifications?: {\n manifest: boolean;\n content: boolean;\n structure: boolean;\n };\n /** The computed hashes */\n computedHashes?: {\n manifestHash: string;\n contentHash: string;\n structureHash: string;\n combinedHash: string;\n };\n /** The expected hashes (if known) */\n expectedHashes?: ExtensionHash;\n /** Error message if status is 'error' */\n error?: string;\n}\n\n/**\n * Compute SHA256 hash of a string\n */\nexport function sha256(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n}\n\n/**\n * Compute hashes for an extension from its files\n */\nexport function computeExtensionHashes(\n extensionId: string,\n version: string,\n files: Map<string, string>\n): Omit<ExtensionHash, 'recordedAt' | 'source'> {\n // Manifest hash\n const manifestContent = files.get('package.json') ?? '';\n const manifestHash = sha256(manifestContent);\n\n // Content hash - concatenate all JS files sorted by path\n const jsFiles = Array.from(files.entries())\n .filter(([path]) => path.endsWith('.js') || path.endsWith('.ts'))\n .sort(([a], [b]) => a.localeCompare(b));\n\n const contentHash = sha256(jsFiles.map(([, content]) => content).join('\\n'));\n\n // Structure hash - sorted list of all file paths\n const sortedPaths = Array.from(files.keys()).sort();\n const structureHash = sha256(sortedPaths.join('\\n'));\n\n // Combined hash\n const combinedHash = sha256(`${manifestHash}:${contentHash}:${structureHash}`);\n\n return {\n extensionId,\n version,\n manifestHash,\n contentHash,\n structureHash,\n combinedHash,\n };\n}\n\n/**\n * Verify extension integrity against known hashes\n */\nexport function verifyIntegrity(\n extensionId: string,\n version: string,\n files: Map<string, string>,\n knownHashes: Map<string, ExtensionHash>\n): IntegrityResult {\n try {\n // Compute current hashes\n const computed = computeExtensionHashes(extensionId, version, files);\n\n // Look up known hash\n const key = `${extensionId}@${version}`;\n const expected = knownHashes.get(key);\n\n if (!expected) {\n return {\n extensionId,\n version,\n status: 'unknown',\n computedHashes: {\n ...computed,\n },\n };\n }\n\n // Compare hashes\n const manifestModified = computed.manifestHash !== expected.manifestHash;\n const contentModified = computed.contentHash !== expected.contentHash;\n const structureModified = computed.structureHash !== expected.structureHash;\n\n if (manifestModified || contentModified || structureModified) {\n return {\n extensionId,\n version,\n status: 'modified',\n modifications: {\n manifest: manifestModified,\n content: contentModified,\n structure: structureModified,\n },\n computedHashes: {\n ...computed,\n },\n expectedHashes: expected,\n };\n }\n\n return {\n extensionId,\n version,\n status: 'verified',\n computedHashes: {\n ...computed,\n },\n expectedHashes: expected,\n };\n } catch (error) {\n return {\n extensionId,\n version,\n status: 'error',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Create a hash record for an extension (for adding to the database)\n */\nexport function createHashRecord(\n extensionId: string,\n version: string,\n files: Map<string, string>,\n source: ExtensionHash['source'] = 'manual'\n): ExtensionHash {\n const hashes = computeExtensionHashes(extensionId, version, files);\n return {\n ...hashes,\n recordedAt: new Date().toISOString(),\n source,\n };\n}\n","/**\n * Known-Good Hash Database\n *\n * This module manages the database of known-good extension hashes.\n * The database can be:\n * 1. Bundled with the package (for critical extensions)\n * 2. Downloaded from a remote server (for community-maintained hashes)\n * 3. Locally maintained by the user\n *\n * IMPORTANT: This is a static snapshot. For production use, consider:\n * - Fetching from VS Code Marketplace API\n * - Community-maintained hash repository\n * - User-generated baseline from clean install\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ExtensionHash } from './integrity-verifier.js';\n\n/**\n * Hash database structure\n */\nexport interface HashDatabase {\n version: string;\n updatedAt: string;\n hashes: ExtensionHash[];\n}\n\n/**\n * In-memory cache of loaded hashes\n */\nlet hashCache: Map<string, ExtensionHash> | null = null;\n\n/**\n * Default path for local hash database\n */\nexport function getDefaultDatabasePath(): string {\n const homeDir = process.env.HOME || process.env.USERPROFILE || '';\n return path.join(homeDir, '.extension-guard', 'hash-database.json');\n}\n\n/**\n * Load hash database from a JSON file\n */\nexport function loadHashDatabase(filePath?: string): Map<string, ExtensionHash> {\n const dbPath = filePath || getDefaultDatabasePath();\n\n if (hashCache && !filePath) {\n return hashCache;\n }\n\n const hashes = new Map<string, ExtensionHash>();\n\n try {\n if (fs.existsSync(dbPath)) {\n const content = fs.readFileSync(dbPath, 'utf8');\n const db: HashDatabase = JSON.parse(content);\n\n for (const hash of db.hashes) {\n const key = `${hash.extensionId}@${hash.version}`;\n hashes.set(key, hash);\n }\n }\n } catch {\n // Silently fail - database might not exist yet\n }\n\n // Also load bundled hashes\n const bundled = getBundledHashes();\n for (const [key, hash] of bundled) {\n if (!hashes.has(key)) {\n hashes.set(key, hash);\n }\n }\n\n if (!filePath) {\n hashCache = hashes;\n }\n\n return hashes;\n}\n\n/**\n * Save hash database to a JSON file\n */\nexport function saveHashDatabase(hashes: Map<string, ExtensionHash>, filePath?: string): void {\n const dbPath = filePath || getDefaultDatabasePath();\n const dir = path.dirname(dbPath);\n\n // Ensure directory exists\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n const db: HashDatabase = {\n version: '1.0',\n updatedAt: new Date().toISOString(),\n hashes: Array.from(hashes.values()),\n };\n\n fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));\n\n // Update cache\n if (!filePath) {\n hashCache = hashes;\n }\n}\n\n/**\n * Add or update a hash in the database\n */\nexport function addHash(hash: ExtensionHash, filePath?: string): void {\n const hashes = loadHashDatabase(filePath);\n const key = `${hash.extensionId}@${hash.version}`;\n hashes.set(key, hash);\n saveHashDatabase(hashes, filePath);\n}\n\n/**\n * Get a hash from the database\n */\nexport function getHash(\n extensionId: string,\n version: string,\n filePath?: string\n): ExtensionHash | undefined {\n const hashes = loadHashDatabase(filePath);\n return hashes.get(`${extensionId}@${version}`);\n}\n\n/**\n * Clear the hash cache (useful for testing)\n */\nexport function clearHashCache(): void {\n hashCache = null;\n}\n\n/**\n * Bundled hashes for critical extensions\n *\n * These are hashes of known-good versions of high-risk extensions.\n * They are bundled with the package to provide baseline protection\n * without requiring network access.\n *\n * NOTE: In production, these should be regularly updated and\n * ideally fetched from a trusted source.\n */\nfunction getBundledHashes(): Map<string, ExtensionHash> {\n const hashes = new Map<string, ExtensionHash>();\n\n // This is a placeholder structure.\n // In production, this would contain actual verified hashes.\n //\n // Example:\n // {\n // extensionId: 'github.copilot',\n // version: '1.388.0',\n // manifestHash: 'abc123...',\n // contentHash: 'def456...',\n // structureHash: 'ghi789...',\n // combinedHash: 'jkl012...',\n // recordedAt: '2026-02-01T00:00:00Z',\n // source: 'marketplace',\n // }\n\n return hashes;\n}\n\n/**\n * Generate a baseline database from currently installed extensions\n * This is useful for users to create their own trusted baseline\n */\nexport async function generateBaseline(\n _extensionPaths: string[],\n _outputPath?: string\n): Promise<{ generated: number; errors: string[] }> {\n // This is implemented in CLI directly for better UX\n // Keeping this function signature for API completeness\n return {\n generated: 0,\n errors: ['Use CLI baseline command instead'],\n };\n}\n","/**\n * Bundle/Minified File Detector\n *\n * Detects if a JavaScript file is bundled/minified output from tools like:\n * - webpack\n * - esbuild\n * - rollup\n * - parcel\n * - vite\n *\n * Bundled files often trigger false positives because:\n * - They contain many library dependencies inlined\n * - Minification creates high-entropy code patterns\n * - Source maps and comments are stripped\n */\n\nexport interface BundleDetectionResult {\n isBundled: boolean;\n confidence: 'high' | 'medium' | 'low';\n reasons: string[];\n bundler?: string;\n}\n\n/**\n * Common bundler signatures in the output\n */\nconst BUNDLER_SIGNATURES: Record<string, RegExp[]> = {\n webpack: [\n /\\/\\*{3}\\/ var __webpack_/,\n /\\/\\*! For license information /,\n /webpackChunk/,\n /__webpack_require__/,\n /\\/\\*\\*\\*\\/ \\(/,\n ],\n esbuild: [\n /\\/\\/ src\\//,\n /__esm\\s*\\(/,\n /__export\\s*\\(/,\n /var __defProp\\s*=/,\n /var __getOwnPropDesc\\s*=/,\n ],\n rollup: [\n /\\/\\*\\* @license/,\n /\\(function \\(global, factory\\)/,\n /typeof exports === 'object'/,\n /define\\(\\['exports'/,\n ],\n parcel: [/parcelRequire/, /@parcel\\/transformer/],\n vite: [/vite\\/modulepreload-polyfill/, /import\\.meta\\.hot/],\n browserify: [/require=\\(function e\\(t,n,r\\)/, /typeof require==\"function\"/],\n};\n\n/**\n * Patterns indicating minified code\n * Note: Currently checked via line length heuristics instead\n */\n// const MINIFICATION_PATTERNS = [\n// /[,;]\\s*[a-z]\\s*=/gi,\n// /\\)\\s*\\{\\s*return\\s+[a-z]\\s*\\(/gi,\n// ];\n\n/**\n * Common chunk patterns\n */\nconst CHUNK_PATTERNS = [\n /\\d+\\.chunk\\.js$/i,\n /chunk-[a-f0-9]+\\.js$/i,\n /\\.bundle\\.js$/i,\n /\\.min\\.js$/i,\n /\\.prod\\.js$/i,\n /vendor[\\.\\-]/i,\n /runtime[\\.\\-][a-f0-9]+\\.js$/i,\n];\n\n/**\n * Detect if a file is a bundled/minified output\n */\nexport function detectBundle(filePath: string, content: string): BundleDetectionResult {\n const reasons: string[] = [];\n let detectedBundler: string | undefined;\n\n // Check filename patterns\n const filename = filePath.split('/').pop() || filePath;\n for (const pattern of CHUNK_PATTERNS) {\n if (pattern.test(filename)) {\n reasons.push(`Filename matches chunk pattern: ${filename}`);\n break;\n }\n }\n\n // Check for bundler signatures\n for (const [bundler, patterns] of Object.entries(BUNDLER_SIGNATURES)) {\n for (const pattern of patterns) {\n if (pattern.test(content)) {\n reasons.push(`Contains ${bundler} signature`);\n detectedBundler = bundler;\n break;\n }\n }\n if (detectedBundler) break;\n }\n\n // Check for minification indicators\n const lines = content.split('\\n');\n const longLineCount = lines.filter((line) => line.length > 500).length;\n const totalLines = lines.length;\n\n if (totalLines > 0 && longLineCount / totalLines > 0.1) {\n reasons.push(`High percentage of long lines (${longLineCount}/${totalLines})`);\n }\n\n // Check for average line length (minified files have very long average)\n const totalChars = content.length;\n const avgLineLength = totalChars / Math.max(totalLines, 1);\n if (avgLineLength > 200) {\n reasons.push(`High average line length (${Math.round(avgLineLength)} chars)`);\n }\n\n // Check for source map reference\n if (/\\/\\/# sourceMappingURL=/.test(content)) {\n reasons.push('Contains source map reference');\n }\n\n // Check for common bundled patterns\n if (/\\(self\\[\"webpackChunk/.test(content)) {\n reasons.push('Contains webpack chunk pattern');\n if (!detectedBundler) detectedBundler = 'webpack';\n }\n\n // Check for many export/import patterns (common in bundled code)\n const exportCount = (content.match(/export\\s*\\{|exports\\./g) || []).length;\n if (exportCount > 20) {\n reasons.push(`Many export statements (${exportCount})`);\n }\n\n // Determine confidence level\n let confidence: 'high' | 'medium' | 'low' = 'low';\n if (detectedBundler || reasons.length >= 3) {\n confidence = 'high';\n } else if (reasons.length >= 2) {\n confidence = 'medium';\n }\n\n return {\n isBundled: reasons.length > 0,\n confidence,\n reasons,\n bundler: detectedBundler,\n };\n}\n\n/**\n * Check if a file path looks like a bundled output location\n */\nexport function isBundleOutputPath(filePath: string): boolean {\n const bundleOutputDirs = [\n '/dist/',\n '/build/',\n '/out/',\n '/lib/',\n '/.output/',\n '/bundle/',\n '/packed/',\n '/compiled/',\n ];\n\n const normalizedPath = filePath.toLowerCase();\n return bundleOutputDirs.some((dir) => normalizedPath.includes(dir));\n}\n\n/**\n * Determine if findings from this file should be treated with reduced severity\n * because it's likely bundled code (which commonly contains many false positives)\n */\nexport function shouldReduceSeverityForBundle(\n filePath: string,\n content: string\n): { reduce: boolean; reason?: string } {\n // First check if it's in a typical bundle output directory\n if (isBundleOutputPath(filePath)) {\n const result = detectBundle(filePath, content);\n if (result.isBundled && result.confidence !== 'low') {\n return {\n reduce: true,\n reason: `Bundled file (${result.bundler || 'detected'}, ${result.confidence} confidence)`,\n };\n }\n }\n\n // Also check files that end with common bundle extensions\n if (/\\.(bundle|min|prod|chunk)\\.js$/i.test(filePath)) {\n return {\n reduce: true,\n reason: 'Bundle filename pattern',\n };\n }\n\n return { reduce: false };\n}\n","import type { Reporter, ReporterOptions } from './reporter.interface.js';\nimport type { FullScanReport, ScanResult, Severity } from '../types/index.js';\n\nconst SEVERITY_ORDER: Record<Severity, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n info: 4,\n};\n\nexport class JsonReporter implements Reporter {\n readonly format = 'json';\n\n generate(report: FullScanReport, options: ReporterOptions = {}): string {\n const { includeEvidence = true, includeSafe = true, minSeverity = 'info' } = options;\n\n const filteredResults = this.filterResults(report.results, {\n includeSafe,\n minSeverity,\n includeEvidence,\n });\n\n const output = {\n ...report,\n results: filteredResults,\n };\n\n return JSON.stringify(output, null, 2);\n }\n\n private filterResults(\n results: ScanResult[],\n options: { includeSafe: boolean; minSeverity: Severity; includeEvidence: boolean }\n ): ScanResult[] {\n let filtered = results;\n\n if (!options.includeSafe) {\n filtered = filtered.filter((r) => r.riskLevel !== 'safe' && r.riskLevel !== 'low');\n }\n\n const minOrder = SEVERITY_ORDER[options.minSeverity];\n\n return filtered.map((result) => {\n const filteredFindings = result.findings.filter(\n (f) => SEVERITY_ORDER[f.severity] <= minOrder\n );\n\n const findingsOutput = options.includeEvidence\n ? filteredFindings\n : filteredFindings.map(({ evidence, ...rest }) => rest);\n\n return {\n ...result,\n findings: findingsOutput as ScanResult['findings'],\n };\n });\n }\n}\n","import type { Reporter, ReporterOptions } from './reporter.interface.js';\nimport type { FullScanReport } from '../types/index.js';\n\ninterface SarifRule {\n id: string;\n name: string;\n shortDescription: { text: string };\n fullDescription: { text: string };\n defaultConfiguration: { level: 'error' | 'warning' | 'note' };\n properties?: { 'security-severity'?: string; tags?: string[] };\n}\n\ninterface SarifResult {\n ruleId: string;\n ruleIndex: number;\n level: 'error' | 'warning' | 'note';\n message: { text: string };\n locations: Array<{\n physicalLocation: {\n artifactLocation: { uri: string };\n region?: { startLine: number; startColumn?: number };\n };\n }>;\n properties?: Record<string, unknown>;\n}\n\ninterface SarifOutput {\n $schema: string;\n version: string;\n runs: Array<{\n tool: {\n driver: {\n name: string;\n version: string;\n informationUri: string;\n rules: SarifRule[];\n };\n };\n results: SarifResult[];\n }>;\n}\n\nconst SEVERITY_TO_LEVEL: Record<string, 'error' | 'warning' | 'note'> = {\n critical: 'error',\n high: 'error',\n medium: 'warning',\n low: 'note',\n info: 'note',\n};\n\nconst SEVERITY_TO_SCORE: Record<string, string> = {\n critical: '9.0',\n high: '7.0',\n medium: '5.0',\n low: '3.0',\n info: '1.0',\n};\n\nexport class SarifReporter implements Reporter {\n readonly format = 'sarif';\n\n generate(report: FullScanReport, _options?: ReporterOptions): string {\n const rules = this.extractRules(report);\n const results = this.extractResults(report, rules);\n\n const sarif: SarifOutput = {\n $schema:\n 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',\n version: '2.1.0',\n runs: [\n {\n tool: {\n driver: {\n name: 'Extension Guard',\n version: report.version,\n informationUri: 'https://github.com/aspect-guard/extension-guard',\n rules,\n },\n },\n results,\n },\n ],\n };\n\n return JSON.stringify(sarif, null, 2);\n }\n\n private extractRules(report: FullScanReport): SarifRule[] {\n const ruleMap = new Map<string, SarifRule>();\n\n for (const result of report.results) {\n for (const finding of result.findings) {\n if (!ruleMap.has(finding.ruleId)) {\n ruleMap.set(finding.ruleId, {\n id: finding.ruleId,\n name: finding.title,\n shortDescription: { text: finding.title },\n fullDescription: { text: finding.description },\n defaultConfiguration: { level: SEVERITY_TO_LEVEL[finding.severity] || 'note' },\n properties: {\n 'security-severity': SEVERITY_TO_SCORE[finding.severity] || '1.0',\n tags: ['security', finding.category],\n },\n });\n }\n }\n }\n\n return Array.from(ruleMap.values());\n }\n\n private extractResults(report: FullScanReport, rules: SarifRule[]): SarifResult[] {\n const results: SarifResult[] = [];\n const ruleIndexMap = new Map(rules.map((r, i) => [r.id, i]));\n\n for (const scanResult of report.results) {\n for (const finding of scanResult.findings) {\n const ruleIndex = ruleIndexMap.get(finding.ruleId) ?? 0;\n\n results.push({\n ruleId: finding.ruleId,\n ruleIndex,\n level: SEVERITY_TO_LEVEL[finding.severity] || 'note',\n message: {\n text: `${finding.title} in ${scanResult.extensionId}: ${finding.description}`,\n },\n locations: [\n {\n physicalLocation: {\n artifactLocation: {\n uri: `${scanResult.extensionId}/${finding.evidence.filePath}`,\n },\n region: finding.evidence.lineNumber\n ? {\n startLine: finding.evidence.lineNumber,\n startColumn: finding.evidence.columnNumber,\n }\n : undefined,\n },\n },\n ],\n properties: {\n extensionId: scanResult.extensionId,\n trustScore: scanResult.trustScore,\n mitreAttackId: finding.mitreAttackId,\n },\n });\n }\n }\n\n return results;\n }\n}\n","import type { Reporter, ReporterOptions } from './reporter.interface.js';\nimport type { FullScanReport, ScanResult, Finding, Severity } from '../types/index.js';\n\nconst SEVERITY_EMOJI: Record<Severity, string> = {\n critical: '🔴',\n high: '🟠',\n medium: '🟡',\n low: '🟢',\n info: '⚪',\n};\n\nconst RISK_EMOJI: Record<string, string> = {\n critical: '⛔',\n high: '🔴',\n medium: '🟡',\n low: '🟢',\n safe: '✅',\n};\n\nexport class MarkdownReporter implements Reporter {\n readonly format = 'markdown';\n\n generate(report: FullScanReport, options: ReporterOptions = {}): string {\n const { includeSafe = false } = options;\n const lines: string[] = [];\n\n lines.push('# Extension Guard Scan Report');\n lines.push('');\n lines.push(`**Scan ID:** \\`${report.scanId}\\``);\n lines.push(`**Date:** ${new Date(report.timestamp).toLocaleString()}`);\n lines.push(`**Extension Guard Version:** ${report.version}`);\n lines.push('');\n\n // Environment\n lines.push('## Environment');\n lines.push('');\n lines.push(`- **OS:** ${report.environment.os}`);\n for (const ide of report.environment.ides) {\n lines.push(`- **${ide.name}:** ${ide.path} (${ide.extensionCount} extensions)`);\n }\n lines.push('');\n\n // Summary\n lines.push('## Summary');\n lines.push('');\n lines.push(`| Metric | Value |`);\n lines.push(`|--------|-------|`);\n lines.push(`| Total Extensions | ${report.totalExtensions} |`);\n lines.push(`| Unique Extensions | ${report.uniqueExtensions} |`);\n lines.push(`| Health Score | ${report.summary.overallHealthScore}% |`);\n lines.push(`| Scan Duration | ${(report.scanDurationMs / 1000).toFixed(2)}s |`);\n lines.push('');\n\n // Risk Level Breakdown\n lines.push('### Risk Level Distribution');\n lines.push('');\n lines.push('| Risk Level | Count |');\n lines.push('|------------|-------|');\n for (const [level, count] of Object.entries(report.summary.byRiskLevel)) {\n if (count > 0 || includeSafe) {\n lines.push(`| ${RISK_EMOJI[level] || ''} ${level} | ${count} |`);\n }\n }\n lines.push('');\n\n // Severity Breakdown\n const totalFindings = Object.values(report.summary.bySeverity).reduce((a, b) => a + b, 0);\n if (totalFindings > 0) {\n lines.push('### Findings by Severity');\n lines.push('');\n lines.push('| Severity | Count |');\n lines.push('|----------|-------|');\n for (const [severity, count] of Object.entries(report.summary.bySeverity)) {\n if (count > 0) {\n lines.push(`| ${SEVERITY_EMOJI[severity as Severity] || ''} ${severity} | ${count} |`);\n }\n }\n lines.push('');\n }\n\n // Critical and High Risk Extensions\n const riskyResults = report.results.filter(\n (r) => r.riskLevel === 'critical' || r.riskLevel === 'high'\n );\n\n if (riskyResults.length > 0) {\n lines.push('## ⚠️ High Risk Extensions');\n lines.push('');\n for (const result of riskyResults) {\n lines.push(...this.formatExtensionResult(result));\n }\n }\n\n // Medium Risk Extensions\n const mediumResults = report.results.filter((r) => r.riskLevel === 'medium');\n if (mediumResults.length > 0) {\n lines.push('## Medium Risk Extensions');\n lines.push('');\n for (const result of mediumResults) {\n lines.push(...this.formatExtensionResult(result));\n }\n }\n\n // Safe Extensions (if requested)\n if (includeSafe) {\n const safeResults = report.results.filter(\n (r) => r.riskLevel === 'safe' || r.riskLevel === 'low'\n );\n if (safeResults.length > 0) {\n lines.push('## ✅ Safe Extensions');\n lines.push('');\n lines.push('| Extension | Version | Trust Score |');\n lines.push('|-----------|---------|-------------|');\n for (const result of safeResults) {\n lines.push(`| ${result.extensionId} | ${result.version} | ${result.trustScore}/100 |`);\n }\n lines.push('');\n }\n }\n\n // Footer\n lines.push('---');\n lines.push('');\n lines.push('*Generated by [Extension Guard](https://github.com/aspect-guard/extension-guard)*');\n\n return lines.join('\\n');\n }\n\n private formatExtensionResult(result: ScanResult): string[] {\n const lines: string[] = [];\n\n lines.push(`### ${RISK_EMOJI[result.riskLevel] || ''} ${result.extensionId}`);\n lines.push('');\n lines.push(`- **Display Name:** ${result.displayName}`);\n lines.push(`- **Version:** ${result.version}`);\n lines.push(`- **Publisher:** ${result.metadata.publisher.name}`);\n lines.push(`- **Trust Score:** ${result.trustScore}/100`);\n lines.push(`- **Risk Level:** ${result.riskLevel}`);\n lines.push('');\n\n if (result.findings.length > 0) {\n lines.push('#### Findings');\n lines.push('');\n for (const finding of result.findings) {\n lines.push(...this.formatFinding(finding));\n }\n }\n\n return lines;\n }\n\n private formatFinding(finding: Finding): string[] {\n const lines: string[] = [];\n const emoji = SEVERITY_EMOJI[finding.severity] || '';\n\n lines.push(`- ${emoji} **${finding.severity.toUpperCase()}:** ${finding.title}`);\n lines.push(` - ${finding.description}`);\n if (finding.evidence.filePath) {\n const location = finding.evidence.lineNumber\n ? `${finding.evidence.filePath}:${finding.evidence.lineNumber}`\n : finding.evidence.filePath;\n lines.push(` - 📍 Location: \\`${location}\\``);\n }\n if (finding.mitreAttackId) {\n lines.push(` - 🎯 MITRE ATT&CK: ${finding.mitreAttackId}`);\n }\n lines.push('');\n\n return lines;\n }\n}\n","/**\n * Policy Loader\n *\n * Loads and validates Extension Guard policy configuration files.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { PolicyConfig } from './policy.types.js';\n\nconst DEFAULT_CONFIG_NAME = '.extension-guard.json';\n\n/**\n * Load and validate a policy configuration file.\n *\n * @param configPath - Optional path to the config file. If not provided,\n * searches for .extension-guard.json in the current directory.\n * @returns The parsed PolicyConfig or null if not found.\n * @throws Error if the file exists but is invalid JSON or fails validation.\n */\nexport async function loadPolicyConfig(configPath?: string): Promise<PolicyConfig | null> {\n const resolvedPath = configPath ?? path.join(process.cwd(), DEFAULT_CONFIG_NAME);\n\n try {\n const content = await fs.readFile(resolvedPath, 'utf-8');\n const config = JSON.parse(content) as unknown;\n\n validatePolicyConfig(config);\n\n return config as PolicyConfig;\n } catch (error) {\n if (isNodeError(error) && error.code === 'ENOENT') {\n return null;\n }\n throw error;\n }\n}\n\n/**\n * Validate that the parsed config matches the expected PolicyConfig schema.\n *\n * @param config - The parsed JSON object\n * @throws Error if validation fails\n */\nfunction validatePolicyConfig(config: unknown): asserts config is PolicyConfig {\n if (typeof config !== 'object' || config === null) {\n throw new Error('Policy config must be an object');\n }\n\n const obj = config as Record<string, unknown>;\n\n // Version is required\n if (typeof obj.version !== 'string') {\n throw new Error('Policy config must have a \"version\" field of type string');\n }\n\n // Validate scanning section if present\n if (obj.scanning !== undefined) {\n validateScanningConfig(obj.scanning);\n }\n\n // Validate policy section if present\n if (obj.policy !== undefined) {\n validatePolicySection(obj.policy);\n }\n}\n\n/**\n * Validate the scanning configuration section.\n */\nfunction validateScanningConfig(scanning: unknown): void {\n if (typeof scanning !== 'object' || scanning === null) {\n throw new Error('scanning must be an object');\n }\n\n const obj = scanning as Record<string, unknown>;\n\n if (obj.minSeverity !== undefined) {\n const validSeverities = ['critical', 'high', 'medium', 'low', 'info'];\n if (!validSeverities.includes(obj.minSeverity as string)) {\n throw new Error(`scanning.minSeverity must be one of: ${validSeverities.join(', ')}`);\n }\n }\n\n if (obj.skipRules !== undefined) {\n if (!Array.isArray(obj.skipRules) || !obj.skipRules.every((r) => typeof r === 'string')) {\n throw new Error('scanning.skipRules must be an array of strings');\n }\n }\n\n if (obj.timeout !== undefined) {\n if (typeof obj.timeout !== 'number' || obj.timeout <= 0) {\n throw new Error('scanning.timeout must be a positive number');\n }\n }\n}\n\n/**\n * Validate the policy configuration section.\n */\nfunction validatePolicySection(policy: unknown): void {\n if (typeof policy !== 'object' || policy === null) {\n throw new Error('policy must be an object');\n }\n\n const obj = policy as Record<string, unknown>;\n\n if (obj.allowlist !== undefined) {\n if (!Array.isArray(obj.allowlist) || !obj.allowlist.every((id) => typeof id === 'string')) {\n throw new Error('policy.allowlist must be an array of extension ID strings');\n }\n }\n\n if (obj.blocklist !== undefined) {\n if (!Array.isArray(obj.blocklist) || !obj.blocklist.every((id) => typeof id === 'string')) {\n throw new Error('policy.blocklist must be an array of extension ID strings');\n }\n }\n\n if (obj.rules !== undefined) {\n validatePolicyRules(obj.rules);\n }\n}\n\n/**\n * Validate the policy rules section.\n */\nfunction validatePolicyRules(rules: unknown): void {\n if (typeof rules !== 'object' || rules === null) {\n throw new Error('policy.rules must be an object');\n }\n\n const obj = rules as Record<string, unknown>;\n const validActions = ['block', 'warn', 'info'];\n\n if (obj.minTrustScore !== undefined) {\n const rule = obj.minTrustScore as Record<string, unknown>;\n if (typeof rule.threshold !== 'number' || rule.threshold < 0 || rule.threshold > 100) {\n throw new Error('minTrustScore.threshold must be a number between 0 and 100');\n }\n if (!validActions.includes(rule.action as string)) {\n throw new Error(`minTrustScore.action must be one of: ${validActions.join(', ')}`);\n }\n }\n\n if (obj.requireVerifiedPublisher !== undefined) {\n const rule = obj.requireVerifiedPublisher as Record<string, unknown>;\n if (typeof rule.enabled !== 'boolean') {\n throw new Error('requireVerifiedPublisher.enabled must be a boolean');\n }\n if (!validActions.includes(rule.action as string)) {\n throw new Error(`requireVerifiedPublisher.action must be one of: ${validActions.join(', ')}`);\n }\n if (rule.exceptions !== undefined) {\n if (!Array.isArray(rule.exceptions) || !rule.exceptions.every((e) => typeof e === 'string')) {\n throw new Error('requireVerifiedPublisher.exceptions must be an array of strings');\n }\n }\n }\n\n if (obj.maxDaysSinceUpdate !== undefined) {\n const rule = obj.maxDaysSinceUpdate as Record<string, unknown>;\n if (typeof rule.days !== 'number' || rule.days <= 0) {\n throw new Error('maxDaysSinceUpdate.days must be a positive number');\n }\n if (!validActions.includes(rule.action as string)) {\n throw new Error(`maxDaysSinceUpdate.action must be one of: ${validActions.join(', ')}`);\n }\n }\n\n if (obj.blockObfuscated !== undefined) {\n const rule = obj.blockObfuscated as Record<string, unknown>;\n if (typeof rule.enabled !== 'boolean') {\n throw new Error('blockObfuscated.enabled must be a boolean');\n }\n if (!validActions.includes(rule.action as string)) {\n throw new Error(`blockObfuscated.action must be one of: ${validActions.join(', ')}`);\n }\n }\n}\n\n/**\n * Type guard for Node.js errors with error codes.\n */\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && 'code' in error;\n}\n","/**\n * Policy Engine\n *\n * Evaluates extension scan results against policy rules to determine compliance.\n */\n\nimport type { PolicyConfig, PolicyViolation } from './policy.types.js';\nimport type { ScanResult } from '../types/index.js';\n\n/**\n * Rule ID for obfuscated code detection.\n * Must match the rule ID in high-obfuscated-code.ts\n */\nconst OBFUSCATION_RULE_ID = 'EG-HIGH-001';\n\n/**\n * Milliseconds in a day for date calculations.\n */\nconst MS_PER_DAY = 1000 * 60 * 60 * 24;\n\n/**\n * Extended metadata interface that may include lastUpdated.\n * The base ExtensionInfo type doesn't include this, but it may be\n * added by the scanner when available from marketplace data.\n */\ninterface ExtendedMetadata {\n lastUpdated?: string;\n publisher: { verified: boolean; name: string };\n}\n\n/**\n * PolicyEngine evaluates scan results against configured policy rules.\n *\n * @example\n * ```typescript\n * const config = await loadPolicyConfig();\n * const engine = new PolicyEngine(config);\n * const violations = engine.evaluate(scanResults);\n *\n * if (engine.hasBlockingViolations()) {\n * console.error('Policy check failed');\n * process.exit(1);\n * }\n * ```\n */\nexport class PolicyEngine {\n private violations: PolicyViolation[] = [];\n\n /**\n * Create a new PolicyEngine instance.\n *\n * @param config - The policy configuration to evaluate against\n */\n constructor(private config: PolicyConfig) {}\n\n /**\n * Evaluate scan results against the configured policy.\n *\n * Checks are applied in this order for each extension:\n * 1. Blocklist - if matched, block immediately and skip other checks\n * 2. Allowlist - if matched, skip all other checks\n * 3. Individual rules (minTrustScore, blockObfuscated, etc.)\n *\n * @param results - Array of scan results to evaluate\n * @returns Array of policy violations found\n */\n evaluate(results: ScanResult[]): PolicyViolation[] {\n this.violations = [];\n\n for (const result of results) {\n const extId = result.extensionId;\n\n // Check blocklist first\n if (this.config.policy?.blocklist?.includes(extId)) {\n this.violations.push({\n extensionId: extId,\n rule: 'blocklist',\n message: 'Extension is blocklisted',\n action: 'block',\n });\n continue; // Skip all other checks for blocklisted extensions\n }\n\n // Check allowlist - skip all other checks if allowed\n if (this.config.policy?.allowlist?.includes(extId)) {\n continue;\n }\n\n // Check individual rules\n this.checkMinTrustScore(result);\n this.checkBlockObfuscated(result);\n this.checkRequireVerifiedPublisher(result);\n this.checkMaxDaysSinceUpdate(result);\n }\n\n return this.violations;\n }\n\n /**\n * Check if there are any violations with 'block' action.\n *\n * @returns true if any blocking violations exist\n */\n hasBlockingViolations(): boolean {\n return this.violations.some((v) => v.action === 'block');\n }\n\n /**\n * Get all violations from the last evaluation.\n *\n * @returns Array of all policy violations\n */\n getViolations(): PolicyViolation[] {\n return this.violations;\n }\n\n /**\n * Check minTrustScore rule.\n */\n private checkMinTrustScore(result: ScanResult): void {\n const rule = this.config.policy?.rules?.minTrustScore;\n if (!rule) return;\n\n if (result.trustScore < rule.threshold) {\n this.violations.push({\n extensionId: result.extensionId,\n rule: 'minTrustScore',\n message: `Trust score ${result.trustScore} below threshold ${rule.threshold}`,\n action: rule.action,\n });\n }\n }\n\n /**\n * Check blockObfuscated rule.\n */\n private checkBlockObfuscated(result: ScanResult): void {\n const rule = this.config.policy?.rules?.blockObfuscated;\n if (!rule?.enabled) return;\n\n const hasObfuscation = result.findings.some((f) => f.ruleId === OBFUSCATION_RULE_ID);\n if (hasObfuscation) {\n this.violations.push({\n extensionId: result.extensionId,\n rule: 'blockObfuscated',\n message: 'Extension contains obfuscated code',\n action: rule.action,\n });\n }\n }\n\n /**\n * Check requireVerifiedPublisher rule.\n */\n private checkRequireVerifiedPublisher(result: ScanResult): void {\n const rule = this.config.policy?.rules?.requireVerifiedPublisher;\n if (!rule?.enabled) return;\n\n const metadata = result.metadata as ExtendedMetadata;\n if (!metadata.publisher.verified) {\n // Check if this extension is in the exceptions list\n if (rule.exceptions?.includes(result.extensionId)) {\n return;\n }\n\n this.violations.push({\n extensionId: result.extensionId,\n rule: 'requireVerifiedPublisher',\n message: 'Extension publisher is not verified',\n action: rule.action,\n });\n }\n }\n\n /**\n * Check maxDaysSinceUpdate rule.\n */\n private checkMaxDaysSinceUpdate(result: ScanResult): void {\n const rule = this.config.policy?.rules?.maxDaysSinceUpdate;\n if (!rule) return;\n\n const metadata = result.metadata as ExtendedMetadata;\n if (!metadata.lastUpdated) return;\n\n const lastUpdatedDate = new Date(metadata.lastUpdated);\n const daysSinceUpdate = Math.floor((Date.now() - lastUpdatedDate.getTime()) / MS_PER_DAY);\n\n if (daysSinceUpdate > rule.days) {\n this.violations.push({\n extensionId: result.extensionId,\n rule: 'maxDaysSinceUpdate',\n message: `Extension not updated in ${daysSinceUpdate} days (max: ${rule.days})`,\n action: rule.action,\n });\n }\n }\n}\n","// Extension Guard Core - Scanning Engine\n// @aspect-guard/core\n\nexport const VERSION = '0.5.0';\n\n// Types\nexport * from './types/index.js';\n\n// Scanner\nexport { ExtensionGuardScanner } from './scanner/scanner.js';\nexport {\n detectIDEPaths,\n IDE_PATHS,\n expandPath,\n getSupportedIDEs,\n isIDEInstalled,\n getIDEExtensionPath,\n} from './scanner/ide-detector.js';\nexport { readExtension, readExtensionsFromDirectory } from './scanner/extension-reader.js';\nexport { collectFiles, shouldCollectFile } from './scanner/file-collector.js';\nexport { categorizeExtension } from './scanner/extension-categorizer.js';\nexport type { ExtensionCategory } from './scanner/extension-categorizer.js';\n\n// Rules\nexport * from './rules/index.js';\nexport { registerBuiltInRules, DETECTION_RULES } from './rules/built-in/index.js';\nexport { adjustFindings } from './rules/finding-adjuster.js';\nexport type { AdjustFindingsOptions } from './rules/finding-adjuster.js';\n\n// Trusted Publishers\nexport {\n TRUSTED_PUBLISHERS,\n TRUSTED_EXTENSION_IDS,\n isTrustedPublisher,\n isTrustedExtension,\n} from './data/trusted-publishers.js';\n\n// Verified Publishers\nexport { VERIFIED_PUBLISHERS, isVerifiedPublisher } from './data/verified-publishers.js';\n\n// Popular Extensions\nexport {\n ALL_POPULAR_EXTENSIONS,\n MEGA_POPULAR_EXTENSIONS,\n POPULAR_EXTENSIONS,\n getPopularityTier,\n isMegaPopular,\n isPopular,\n} from './data/popular-extensions.js';\nexport type { PopularExtension } from './data/popular-extensions.js';\n\n// Bundle Detection\nexport {\n detectBundle,\n isBundleOutputPath,\n shouldReduceSeverityForBundle,\n} from './analyzers/bundle-detector.js';\nexport type { BundleDetectionResult } from './analyzers/bundle-detector.js';\n\n// Reporter\nexport * from './reporter/index.js';\n\n// Policy\nexport * from './policy/index.js';\n\n// Integrity Verification\nexport * from './integrity/index.js';\n"],"mappings":"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","names":["os","randomUUID","fs","path","stat","fs","path","stat","match","path","fs","path","randomUUID","SEVERITY_ORDER","fs","path"]}
1
+ {"version":3,"sources":["../src/types/severity.ts","../src/scanner/scanner.ts","../src/scanner/ide-detector.ts","../src/scanner/extension-reader.ts","../src/scanner/file-collector.ts","../src/rules/rule-registry.ts","../src/rules/rule-engine.ts","../src/data/trusted-publishers.ts","../src/data/verified-publishers.ts","../src/data/popular-extensions.ts","../src/rules/finding-adjuster.ts","../src/rules/built-in/crit-data-exfiltration.ts","../src/rules/built-in/crit-remote-execution.ts","../src/rules/built-in/crit-credential-access.ts","../src/rules/built-in/high-suspicious-network.ts","../src/rules/built-in/high-obfuscated-code.ts","../src/rules/built-in/high-hardcoded-secret.ts","../src/rules/built-in/med-excessive-activation.ts","../src/rules/built-in/index.ts","../src/scanner/extension-categorizer.ts","../src/integrity/integrity-verifier.ts","../src/integrity/hash-database.ts","../src/analyzers/bundle-detector.ts","../src/reporter/json-reporter.ts","../src/reporter/sarif-reporter.ts","../src/reporter/markdown-reporter.ts","../src/policy/policy-loader.ts","../src/policy/policy-engine.ts","../src/index.ts"],"sourcesContent":["export type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';\n\nexport type RiskLevel = 'critical' | 'high' | 'medium' | 'low' | 'safe';\n\nexport const SEVERITY_ORDER: Record<Severity, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n info: 4,\n};\n\nexport function compareSeverity(a: Severity, b: Severity): number {\n return SEVERITY_ORDER[a] - SEVERITY_ORDER[b];\n}\n\nexport function isAtLeastSeverity(severity: Severity, minimum: Severity): boolean {\n return SEVERITY_ORDER[severity] <= SEVERITY_ORDER[minimum];\n}\n","import * as os from 'node:os';\nimport { randomUUID } from 'node:crypto';\nimport type {\n ScanOptions,\n FullScanReport,\n ScanResult,\n ScanSummary,\n RiskLevel,\n Severity,\n FindingCategory,\n DetectedIDE,\n ExtensionManifest,\n IntegrityInfo,\n} from '../types/index.js';\nimport { detectIDEPaths } from './ide-detector.js';\nimport { readExtensionsFromDirectory } from './extension-reader.js';\nimport { collectFiles } from './file-collector.js';\nimport { VERSION } from '../index.js';\nimport { RuleEngine } from '../rules/rule-engine.js';\nimport { adjustFindings } from '../rules/finding-adjuster.js';\nimport { registerBuiltInRules } from '../rules/built-in/index.js';\nimport { categorizeExtension } from './extension-categorizer.js';\nimport { verifyIntegrity, loadHashDatabase } from '../integrity/index.js';\nimport type { ExtensionHash } from '../integrity/index.js';\n\n// Register built-in rules once at module load\nlet rulesRegistered = false;\nfunction ensureRulesRegistered(): void {\n if (!rulesRegistered) {\n registerBuiltInRules();\n rulesRegistered = true;\n }\n}\n\nconst DEFAULT_OPTIONS: Required<ScanOptions> = {\n idePaths: [],\n autoDetect: true,\n severity: 'info',\n rules: [],\n skipRules: [],\n concurrency: 4,\n timeout: 30000,\n verifyIntegrity: false,\n hashDatabasePath: '',\n};\n\nconst SEVERITY_PENALTY: Record<Severity, number> = {\n critical: 35,\n high: 18,\n medium: 8,\n low: 3,\n info: 1,\n};\n\nexport class ExtensionGuardScanner {\n private options: Required<ScanOptions>;\n private ruleEngine: RuleEngine;\n private hashDatabase: Map<string, ExtensionHash> | null = null;\n\n constructor(options?: Partial<ScanOptions>) {\n ensureRulesRegistered();\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.ruleEngine = new RuleEngine({\n rules: this.options.rules.length > 0 ? this.options.rules : undefined,\n skipRules: this.options.skipRules.length > 0 ? this.options.skipRules : undefined,\n minSeverity: this.options.severity,\n });\n\n // Load hash database if integrity verification is enabled\n if (this.options.verifyIntegrity) {\n this.hashDatabase = loadHashDatabase(this.options.hashDatabasePath || undefined);\n }\n }\n\n async scan(options?: Partial<ScanOptions>): Promise<FullScanReport> {\n const startTime = Date.now();\n const mergedOptions = { ...this.options, ...options };\n\n // Detect IDE paths\n let ides: DetectedIDE[];\n if (mergedOptions.autoDetect && mergedOptions.idePaths.length === 0) {\n ides = detectIDEPaths();\n } else {\n ides = mergedOptions.idePaths.map((p) => ({\n name: 'Custom',\n path: p,\n extensionCount: 0,\n }));\n }\n\n // Collect all extensions\n const allExtensions = await Promise.all(\n ides.map((ide) => readExtensionsFromDirectory(ide.path))\n );\n\n const extensionMap = new Map<\n string,\n { ide: DetectedIDE; ext: Awaited<ReturnType<typeof readExtensionsFromDirectory>>[number] }\n >();\n for (let i = 0; i < ides.length; i++) {\n const ide = ides[i]!;\n for (const ext of allExtensions[i]!) {\n if (!extensionMap.has(ext.id)) {\n extensionMap.set(ext.id, { ide, ext });\n }\n }\n // Update extension count\n ide.extensionCount = allExtensions[i]!.length;\n }\n\n // Scan extensions concurrently with configurable parallelism\n const extensions = Array.from(extensionMap.values()).map(({ ext }) => ext);\n const results = await this.scanExtensionsConcurrently(extensions, mergedOptions.concurrency);\n\n // Calculate summary\n const summary = this.calculateSummary(results);\n\n return {\n scanId: randomUUID(),\n version: VERSION,\n timestamp: new Date().toISOString(),\n environment: {\n os: `${os.platform()} ${os.release()}`,\n ides,\n },\n totalExtensions: Array.from(allExtensions).reduce((sum, arr) => sum + arr.length, 0),\n uniqueExtensions: extensionMap.size,\n results,\n summary,\n scanDurationMs: Date.now() - startTime,\n };\n }\n\n /**\n * Scan multiple extensions concurrently with a configurable pool size.\n * Uses a simple semaphore pattern to limit concurrent operations.\n */\n private async scanExtensionsConcurrently(\n extensions: Awaited<ReturnType<typeof readExtensionsFromDirectory>>,\n concurrency: number\n ): Promise<ScanResult[]> {\n const results: ScanResult[] = new Array(extensions.length);\n let currentIndex = 0;\n\n const worker = async (): Promise<void> => {\n while (currentIndex < extensions.length) {\n const index = currentIndex++;\n const ext = extensions[index];\n if (ext) {\n results[index] = await this.scanExtension(ext);\n }\n }\n };\n\n // Start 'concurrency' number of workers\n const workers = Array.from({ length: Math.min(concurrency, extensions.length) }, () =>\n worker()\n );\n await Promise.all(workers);\n\n return results.filter((r): r is ScanResult => r !== undefined);\n }\n\n private async scanExtension(\n ext: Awaited<ReturnType<typeof readExtensionsFromDirectory>>[number]\n ): Promise<ScanResult> {\n const startTime = Date.now();\n const files = await collectFiles(ext.installPath);\n\n // Parse manifest for rule engine\n const manifestContent = files.get('package.json');\n let manifest: ExtensionManifest = {\n name: ext.id.split('.')[1] || ext.id,\n publisher: ext.publisher.name,\n version: ext.version,\n };\n if (manifestContent) {\n try {\n manifest = JSON.parse(manifestContent);\n } catch {\n // Use default manifest\n }\n }\n\n // Run rules\n const rawFindings = this.ruleEngine.run(files, manifest);\n\n // Infer extension category and adjust findings for expected behavior\n // Also apply soft trust for known publishers\n const category = categorizeExtension(manifest);\n const findings = adjustFindings(rawFindings, category, {\n publisher: ext.publisher.name,\n extensionId: ext.id,\n });\n\n // Calculate trust score\n const trustScore = this.calculateTrustScore(findings);\n let riskLevel = this.calculateRiskLevel(trustScore, findings);\n\n // Verify integrity if enabled\n let integrity: IntegrityInfo | undefined;\n if (this.options.verifyIntegrity && this.hashDatabase) {\n const result = verifyIntegrity(ext.id, ext.version, files, this.hashDatabase);\n integrity = {\n status: result.status,\n modifications: result.modifications,\n hash: result.computedHashes?.combinedHash,\n };\n\n // If extension is modified, override risk level to critical\n if (result.status === 'modified') {\n riskLevel = 'critical';\n // Add a synthetic finding for the integrity violation\n findings.unshift({\n id: `integrity-${ext.id}`,\n ruleId: 'EG-CRIT-100',\n severity: 'critical',\n category: 'supply-chain',\n title: 'Extension Integrity Compromised',\n description:\n `Extension files have been modified from known-good version. Modifications: ${\n result.modifications?.manifest ? 'manifest ' : ''\n }${result.modifications?.content ? 'content ' : ''}${\n result.modifications?.structure ? 'structure' : ''\n }`.trim(),\n evidence: {\n filePath: ext.installPath,\n matchedPattern: 'integrity-violation',\n },\n remediation:\n 'Reinstall the extension from the official marketplace. If this persists, report to the extension author.',\n });\n }\n } else if (this.options.verifyIntegrity) {\n integrity = { status: 'skipped' };\n }\n\n return {\n extensionId: ext.id,\n displayName: ext.displayName,\n version: ext.version,\n trustScore,\n riskLevel,\n findings,\n metadata: ext,\n analyzedFiles: files.size,\n scanDurationMs: Date.now() - startTime,\n integrity,\n };\n }\n\n private calculateTrustScore(findings: ScanResult['findings']): number {\n let score = 100;\n\n // Count findings by rule to avoid excessive penalty from bundled code\n const findingsByRule = new Map<string, number>();\n\n for (const finding of findings) {\n const count = findingsByRule.get(finding.ruleId) ?? 0;\n\n // Cap each rule's penalty contribution (max 5 findings per rule for scoring)\n // This prevents bundled code with 1000+ similar patterns from zeroing the score\n if (count < 5) {\n score -= SEVERITY_PENALTY[finding.severity];\n findingsByRule.set(finding.ruleId, count + 1);\n }\n }\n\n // Clamp to [0, 100]\n return Math.max(0, Math.min(100, score));\n }\n\n private calculateRiskLevel(trustScore: number, findings: ScanResult['findings']): RiskLevel {\n // Only non-downgraded critical/high findings affect risk level\n // (downgraded findings have \"[Downgraded:\" in description)\n const realFindings = findings.filter((f) => !f.description?.includes('[Downgraded:'));\n\n // If any real critical finding, always critical\n if (realFindings.some((f) => f.severity === 'critical')) {\n return 'critical';\n }\n // If any real high finding, at least high\n if (realFindings.some((f) => f.severity === 'high')) {\n return 'high';\n }\n\n // Otherwise, base on trust score\n if (trustScore >= 90) return 'safe';\n if (trustScore >= 70) return 'low';\n if (trustScore >= 45) return 'medium';\n if (trustScore >= 20) return 'high';\n return 'critical';\n }\n\n private calculateSummary(results: ScanResult[]): ScanSummary {\n const byRiskLevel: Record<RiskLevel, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n safe: 0,\n };\n\n const bySeverity: Record<Severity, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n info: 0,\n };\n\n const byCategory: Partial<Record<FindingCategory, number>> = {};\n\n for (const result of results) {\n byRiskLevel[result.riskLevel]++;\n\n for (const finding of result.findings) {\n bySeverity[finding.severity]++;\n byCategory[finding.category] = (byCategory[finding.category] ?? 0) + 1;\n }\n }\n\n // Collect top findings (sorted by severity)\n const allFindings = results.flatMap((r) => r.findings);\n const severityOrder: Record<Severity, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n info: 4,\n };\n const topFindings = allFindings\n .sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity])\n .slice(0, 10);\n\n // Calculate overall health score\n const totalExtensions = results.length;\n const safeCount = byRiskLevel.safe + byRiskLevel.low;\n const overallHealthScore =\n totalExtensions > 0 ? Math.round((safeCount / totalExtensions) * 100) : 100;\n\n return {\n byRiskLevel,\n bySeverity,\n byCategory,\n topFindings,\n overallHealthScore,\n };\n }\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { DetectedIDE } from '../types/index.js';\n\n/**\n * IDE extension paths organized by IDE name.\n * Each IDE has multiple possible paths to support:\n * - Different OS (Windows, macOS, Linux)\n * - Different installation methods (user, system, portable)\n * - Remote development scenarios (SSH, WSL, containers)\n *\n * Paths use these placeholders:\n * - ~ : User home directory\n * - %USERPROFILE% : Windows user profile\n * - %APPDATA% : Windows AppData/Roaming\n * - %LOCALAPPDATA% : Windows AppData/Local\n *\n * References:\n * - https://code.visualstudio.com/docs/editor/extension-marketplace\n * - https://code.visualstudio.com/docs/remote/troubleshooting\n * - https://vscodium.com/\n * - https://zed.dev/docs/extensions/installing-extensions\n */\nexport const IDE_PATHS: Record<string, string[]> = {\n // VS Code - Standard installation\n 'VS Code': [\n // Linux & macOS\n '~/.vscode/extensions',\n // Windows\n '%USERPROFILE%/.vscode/extensions',\n '%USERPROFILE%\\\\.vscode\\\\extensions',\n ],\n\n // VS Code Insiders - Preview builds\n 'VS Code Insiders': [\n // Linux & macOS\n '~/.vscode-insiders/extensions',\n // Windows\n '%USERPROFILE%/.vscode-insiders/extensions',\n '%USERPROFILE%\\\\.vscode-insiders\\\\extensions',\n ],\n\n // VS Code Server - Remote SSH connections\n 'VS Code Server': ['~/.vscode-server/extensions'],\n\n // VS Code Server Insiders - Remote SSH for Insiders\n 'VS Code Server Insiders': ['~/.vscode-server-insiders/extensions'],\n\n // Cursor - AI-powered code editor (VS Code fork)\n // https://cursor.com\n Cursor: [\n // Linux & macOS\n '~/.cursor/extensions',\n // Windows\n '%USERPROFILE%/.cursor/extensions',\n '%USERPROFILE%\\\\.cursor\\\\extensions',\n // macOS alternate location\n '~/Library/Application Support/Cursor/User/extensions',\n ],\n\n // Cursor Server - Remote Cursor connections\n 'Cursor Server': ['~/.cursor-server/extensions'],\n\n // Windsurf - Codeium AI IDE (VS Code fork)\n // https://codeium.com/windsurf\n Windsurf: [\n // Linux & macOS\n '~/.windsurf/extensions',\n // Windows\n '%USERPROFILE%/.windsurf/extensions',\n '%USERPROFILE%\\\\.windsurf\\\\extensions',\n // macOS alternate location\n '~/Library/Application Support/Windsurf/extensions',\n ],\n\n // Windsurf Server - Remote Windsurf connections\n 'Windsurf Server': ['~/.windsurf-server/extensions'],\n\n // Trae - ByteDance AI IDE (VS Code fork)\n // https://www.trae.ai / https://www.marscode.com\n Trae: [\n // Linux & macOS\n '~/.trae/extensions',\n // Windows\n '%USERPROFILE%/.trae/extensions',\n '%USERPROFILE%\\\\.trae\\\\extensions',\n ],\n\n // VSCodium - Open source VS Code without telemetry\n // https://vscodium.com\n VSCodium: [\n // Linux & macOS\n '~/.vscode-oss/extensions',\n // Windows\n '%USERPROFILE%/.vscode-oss/extensions',\n '%USERPROFILE%\\\\.vscode-oss\\\\extensions',\n // Flatpak installation (Linux)\n '~/.var/app/com.vscodium.codium/data/codium/extensions',\n ],\n\n // VSCodium Insiders\n 'VSCodium Insiders': [\n '~/.vscode-oss-insiders/extensions',\n '%USERPROFILE%/.vscode-oss-insiders/extensions',\n ],\n\n // Code - OSS (open source build from Microsoft repo)\n 'Code - OSS': ['~/.config/Code - OSS/extensions', '~/.vscode-oss/extensions'],\n\n // Positron - Posit's data science IDE (VS Code fork)\n // https://github.com/posit-dev/positron\n Positron: [\n '~/.positron/extensions',\n '%USERPROFILE%/.positron/extensions',\n '~/Library/Application Support/Positron/extensions',\n ],\n\n // Theia - Eclipse Theia IDE (VS Code compatible)\n // https://theia-ide.org\n Theia: ['~/.theia/extensions', '%USERPROFILE%/.theia/extensions'],\n\n // OpenVSCode Server - Web-based VS Code\n // https://github.com/gitpod-io/openvscode-server\n 'OpenVSCode Server': ['~/.openvscode-server/extensions'],\n\n // code-server - VS Code in the browser\n // https://github.com/coder/code-server\n 'code-server': ['~/.local/share/code-server/extensions', '~/.config/code-server/extensions'],\n\n // GitHub Codespaces (when accessed locally)\n 'GitHub Codespaces': ['~/.codespaces/.vscode-remote/extensions'],\n\n // Gitpod\n Gitpod: ['/workspace/.gitpod/extensions', '~/.gitpod/extensions'],\n\n // DevPod\n DevPod: ['~/.devpod/extensions'],\n\n // Lapce - Lightning-fast native code editor (has its own extension format but partially compatible)\n // https://lapce.dev\n // Note: Lapce uses a different extension format, included for future compatibility\n // Lapce: [\n // '~/.lapce/plugins',\n // '~/Library/Application Support/Lapce/plugins',\n // ],\n\n // Zed - High-performance editor (different extension format, not VS Code compatible)\n // https://zed.dev\n // Note: Zed uses its own extension format, not VS Code compatible\n // Included as reference for potential future support\n // Zed: [\n // '~/Library/Application Support/Zed/extensions',\n // '~/.local/share/zed/extensions',\n // ],\n};\n\n/**\n * Expand path placeholders to actual paths\n */\nexport function expandPath(inputPath: string): string {\n let result = inputPath;\n const home = os.homedir();\n\n // Expand ~ to home directory\n if (result.startsWith('~/')) {\n result = path.join(home, result.slice(2));\n } else if (result.startsWith('~\\\\')) {\n result = path.join(home, result.slice(2));\n } else if (result === '~') {\n result = home;\n }\n\n // Windows environment variables\n if (process.platform === 'win32') {\n result = result.replace(/%USERPROFILE%/gi, home);\n result = result.replace(\n /%APPDATA%/gi,\n process.env.APPDATA || path.join(home, 'AppData', 'Roaming')\n );\n result = result.replace(\n /%LOCALAPPDATA%/gi,\n process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local')\n );\n } else {\n // On non-Windows, just remove Windows-style placeholders if they exist\n result = result.replace(/%USERPROFILE%/gi, home);\n }\n\n // Normalize path separators for current OS\n return path.normalize(result);\n}\n\n/**\n * Count extensions in a directory\n */\nfunction countExtensions(dirPath: string): number {\n try {\n const entries = fs.readdirSync(dirPath, { withFileTypes: true });\n // Count directories that look like extensions (contain package.json or have publisher.name format)\n return entries.filter((entry) => {\n if (!entry.isDirectory()) return false;\n // Skip hidden directories and common non-extension directories\n if (entry.name.startsWith('.')) return false;\n if (entry.name === 'node_modules') return false;\n return true;\n }).length;\n } catch {\n return 0;\n }\n}\n\n/**\n * Detect all installed IDE extension paths\n */\nexport function detectIDEPaths(): DetectedIDE[] {\n const detected: DetectedIDE[] = [];\n\n for (const [ideName, paths] of Object.entries(IDE_PATHS)) {\n for (const idePath of paths) {\n const expandedPath = expandPath(idePath);\n if (fs.existsSync(expandedPath)) {\n const extensionCount = countExtensions(expandedPath);\n // Only add if there are actually extensions (or the directory exists)\n if (extensionCount > 0) {\n detected.push({\n name: ideName,\n path: expandedPath,\n extensionCount,\n });\n break; // Found this IDE, move to next\n }\n }\n }\n }\n\n return detected;\n}\n\n/**\n * Get list of all supported IDE names\n */\nexport function getSupportedIDEs(): string[] {\n return Object.keys(IDE_PATHS);\n}\n\n/**\n * Check if a specific IDE is installed\n */\nexport function isIDEInstalled(ideName: string): boolean {\n const paths = IDE_PATHS[ideName];\n if (!paths) return false;\n\n return paths.some((p) => {\n const expanded = expandPath(p);\n return fs.existsSync(expanded) && countExtensions(expanded) > 0;\n });\n}\n\n/**\n * Get the extension path for a specific IDE\n */\nexport function getIDEExtensionPath(ideName: string): string | null {\n const paths = IDE_PATHS[ideName];\n if (!paths) return null;\n\n for (const p of paths) {\n const expanded = expandPath(p);\n if (fs.existsSync(expanded)) {\n return expanded;\n }\n }\n\n return null;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { ExtensionInfo, ExtensionManifest } from '../types/index.js';\n\nexport async function readExtension(extensionPath: string): Promise<ExtensionInfo | null> {\n try {\n const packageJsonPath = path.join(extensionPath, 'package.json');\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const manifest: ExtensionManifest = JSON.parse(content);\n\n if (!manifest.name || !manifest.publisher || !manifest.version) {\n return null;\n }\n\n const stats = await getDirectoryStats(extensionPath);\n\n const repository =\n typeof manifest.repository === 'string' ? manifest.repository : manifest.repository?.url;\n\n return {\n id: `${manifest.publisher}.${manifest.name}`,\n displayName: manifest.displayName ?? manifest.name,\n version: manifest.version,\n publisher: {\n name: manifest.publisher,\n verified: false,\n },\n description: manifest.description ?? '',\n categories: manifest.categories ?? [],\n activationEvents: manifest.activationEvents ?? [],\n extensionDependencies: manifest.extensionDependencies ?? [],\n installPath: extensionPath,\n engines: { vscode: manifest.engines?.vscode ?? '*' },\n repository,\n license: manifest.license,\n fileCount: stats.fileCount,\n totalSize: stats.totalSize,\n };\n } catch {\n return null;\n }\n}\n\nasync function getDirectoryStats(\n dirPath: string\n): Promise<{ fileCount: number; totalSize: number }> {\n let fileCount = 0;\n let totalSize = 0;\n\n async function walk(currentPath: string): Promise<void> {\n try {\n const entries = await fs.readdir(currentPath, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(currentPath, entry.name);\n if (entry.isDirectory()) {\n if (entry.name !== 'node_modules') {\n await walk(fullPath);\n }\n } else {\n fileCount++;\n try {\n const stat = await fs.stat(fullPath);\n totalSize += stat.size;\n } catch {\n // Skip files we can't stat\n }\n }\n }\n } catch {\n // Skip directories we can't read\n }\n }\n\n await walk(dirPath);\n return { fileCount, totalSize };\n}\n\nexport async function readExtensionsFromDirectory(directoryPath: string): Promise<ExtensionInfo[]> {\n const extensions: ExtensionInfo[] = [];\n\n try {\n const entries = await fs.readdir(directoryPath, { withFileTypes: true });\n const directories = entries.filter((entry) => entry.isDirectory());\n\n const results = await Promise.all(\n directories.map((dir) => readExtension(path.join(directoryPath, dir.name)))\n );\n\n for (const result of results) {\n if (result) {\n extensions.push(result);\n }\n }\n } catch {\n return [];\n }\n\n return extensions;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nconst COLLECTED_EXTENSIONS = new Set(['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs', '.json']);\n\nconst IGNORED_DIRECTORIES = new Set(['node_modules', '.git', '.svn', '.hg', '__pycache__']);\n\nconst IGNORED_PATTERNS = [/\\.min\\.js$/, /\\.map$/, /\\.d\\.ts$/];\n\nconst MAX_FILE_SIZE = 1024 * 1024; // 1MB\n\nexport function shouldCollectFile(filePath: string): boolean {\n const ext = path.extname(filePath).toLowerCase();\n\n if (!COLLECTED_EXTENSIONS.has(ext)) {\n return false;\n }\n\n const parts = filePath.split(path.sep);\n for (const part of parts) {\n if (IGNORED_DIRECTORIES.has(part)) {\n return false;\n }\n }\n\n for (const pattern of IGNORED_PATTERNS) {\n if (pattern.test(filePath)) {\n return false;\n }\n }\n\n return true;\n}\n\nexport async function collectFiles(extensionPath: string): Promise<Map<string, string>> {\n const files = new Map<string, string>();\n\n async function walk(currentPath: string, relativePath: string): Promise<void> {\n try {\n const entries = await fs.readdir(currentPath, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(currentPath, entry.name);\n const relPath = relativePath ? path.join(relativePath, entry.name) : entry.name;\n\n if (entry.isDirectory()) {\n if (!IGNORED_DIRECTORIES.has(entry.name)) {\n await walk(fullPath, relPath);\n }\n } else if (entry.isFile()) {\n if (shouldCollectFile(relPath)) {\n try {\n const stat = await fs.stat(fullPath);\n if (stat.size <= MAX_FILE_SIZE) {\n const content = await fs.readFile(fullPath, 'utf-8');\n files.set(relPath, content);\n }\n } catch {\n // Skip files we can't read\n }\n }\n }\n }\n } catch {\n // Skip directories we can't access\n }\n }\n\n await walk(extensionPath, '');\n return files;\n}\n","import type { DetectionRule } from './rule.interface.js';\n\nclass RuleRegistry {\n private rules: Map<string, DetectionRule> = new Map();\n\n register(rule: DetectionRule): void {\n this.rules.set(rule.id, rule);\n }\n\n get(id: string): DetectionRule | undefined {\n return this.rules.get(id);\n }\n\n getAll(): DetectionRule[] {\n return Array.from(this.rules.values());\n }\n\n getEnabled(): DetectionRule[] {\n return this.getAll().filter((rule) => rule.enabled);\n }\n\n getByCategory(category: string): DetectionRule[] {\n return this.getAll().filter((rule) => rule.category === category);\n }\n\n getBySeverity(severity: string): DetectionRule[] {\n return this.getAll().filter((rule) => rule.severity === severity);\n }\n\n clear(): void {\n this.rules.clear();\n }\n}\n\nexport const ruleRegistry = new RuleRegistry();\n","import type { ExtensionManifest, Finding, Severity } from '../types/index.js';\nimport { SEVERITY_ORDER } from '../types/index.js';\nimport type { DetectionRule, Evidence } from './rule.interface.js';\nimport { ruleRegistry } from './rule-registry.js';\nimport { randomUUID } from 'node:crypto';\n\nexport interface RuleEngineOptions {\n rules?: string[];\n skipRules?: string[];\n minSeverity?: Severity;\n}\n\nexport class RuleEngine {\n private options: RuleEngineOptions;\n\n constructor(options: RuleEngineOptions = {}) {\n this.options = options;\n }\n\n run(files: Map<string, string>, manifest: ExtensionManifest): Finding[] {\n const findings: Finding[] = [];\n const rules = this.getApplicableRules();\n\n for (const rule of rules) {\n try {\n const evidences = rule.detect(files, manifest);\n for (const evidence of evidences) {\n findings.push(this.createFinding(rule, evidence));\n }\n } catch {\n // Rule failed, continue with other rules\n }\n }\n\n return findings;\n }\n\n private getApplicableRules(): DetectionRule[] {\n let rules = ruleRegistry.getEnabled();\n\n if (this.options.rules && this.options.rules.length > 0) {\n rules = rules.filter((r) => this.options.rules!.includes(r.id));\n }\n\n if (this.options.skipRules && this.options.skipRules.length > 0) {\n rules = rules.filter((r) => !this.options.skipRules!.includes(r.id));\n }\n\n if (this.options.minSeverity) {\n const minOrder = SEVERITY_ORDER[this.options.minSeverity];\n rules = rules.filter((r) => SEVERITY_ORDER[r.severity] <= minOrder);\n }\n\n return rules;\n }\n\n private createFinding(rule: DetectionRule, evidence: Evidence): Finding {\n return {\n id: randomUUID(),\n ruleId: rule.id,\n severity: rule.severity,\n category: rule.category,\n title: rule.name,\n description: rule.description,\n evidence: {\n filePath: evidence.filePath,\n lineNumber: evidence.lineNumber,\n columnNumber: evidence.columnNumber,\n lineContent: evidence.lineContent,\n contextBefore: evidence.contextBefore,\n contextAfter: evidence.contextAfter,\n matchedPattern: evidence.matchedPattern,\n snippet: evidence.snippet,\n },\n mitreAttackId: rule.mitreAttackId,\n };\n }\n}\n","/**\n * List of well-known, trusted publishers.\n *\n * Extensions from these publishers receive \"soft trust\" treatment:\n * - Their findings are downgraded one additional severity level\n * - They are NOT completely bypassed (supply chain attacks can hit anyone)\n *\n * This list is intentionally conservative and includes only:\n * - Major IDE vendors (Microsoft, GitHub)\n * - Well-established tool vendors with long track records\n */\nexport const TRUSTED_PUBLISHERS = [\n // Microsoft official\n 'ms-python',\n 'ms-vscode',\n 'ms-dotnettools',\n 'ms-azuretools',\n 'ms-toolsai',\n 'microsoft',\n 'vscode',\n\n // GitHub\n 'github',\n\n // Major language support\n 'golang',\n 'rust-lang',\n 'redhat',\n 'oracle',\n 'julialang',\n\n // Major tool vendors\n 'esbenp', // Prettier\n 'dbaeumer', // ESLint\n 'eamodio', // GitLens\n\n // Cloud providers\n 'amazonwebservices',\n 'googlecloudtools',\n 'hashicorp',\n\n // Other major vendors\n 'jetbrains',\n 'docker',\n 'mongodb',\n 'prisma',\n 'vscjava', // Microsoft Java\n\n // Popular developer tool vendors\n 'formulahendry', // Code Runner (10M+ downloads)\n 'ritwickdey', // Live Server (50M+ downloads)\n 'humao', // REST Client (5M+ downloads)\n 'rangav', // Thunder Client (3M+ downloads)\n 'mtxr', // SQLTools\n 'cweijan', // Database Client\n\n // Remote development\n 'ms-vscode-remote', // Remote-SSH, Dev Containers, WSL\n\n // Testing\n 'hbenl', // Test Explorer UI\n 'firsttris', // Jest Runner\n 'orta', // vscode-jest\n\n // Notebooks\n 'ms-toolsai', // Jupyter\n];\n\n/**\n * Specific extension IDs that are trusted regardless of publisher.\n * Use this for known extensions from smaller publishers.\n */\nexport const TRUSTED_EXTENSION_IDS = [\n // These are explicitly trusted extension IDs\n 'github.copilot',\n 'github.copilot-chat',\n 'ms-python.python',\n 'ms-python.vscode-pylance',\n 'ms-vscode.cpptools',\n 'golang.go',\n 'rust-lang.rust-analyzer',\n];\n\n/**\n * Check if an extension is from a trusted publisher.\n */\nexport function isTrustedPublisher(publisher: string): boolean {\n const normalized = publisher.toLowerCase();\n return TRUSTED_PUBLISHERS.some((p) => normalized === p.toLowerCase());\n}\n\n/**\n * Check if an extension ID is explicitly trusted.\n */\nexport function isTrustedExtension(extensionId: string): boolean {\n const normalized = extensionId.toLowerCase();\n return TRUSTED_EXTENSION_IDS.some((id) => normalized === id.toLowerCase());\n}\n","/**\n * List of verified publishers from VS Code Marketplace.\n *\n * These publishers have undergone verification by Microsoft and display\n * a verified badge on the marketplace. Extensions from verified publishers\n * are treated similarly to trusted publishers.\n *\n * Note: This list is maintained manually based on known verified publishers.\n * In the future, this could be fetched from the marketplace API.\n */\nexport const VERIFIED_PUBLISHERS = [\n // Microsoft & GitHub (already trusted, but also verified)\n 'microsoft',\n 'ms-python',\n 'ms-vscode',\n 'ms-dotnettools',\n 'ms-azuretools',\n 'ms-toolsai',\n 'ms-vscode-remote',\n 'ms-kubernetes-tools',\n 'ms-playwright',\n 'vscode',\n 'github',\n 'vscjava',\n\n // Major cloud providers (verified)\n 'amazonwebservices',\n 'googlecloudtools',\n 'hashicorp',\n\n // Major language/framework vendors (verified)\n 'golang',\n 'rust-lang',\n 'redhat',\n 'oracle',\n 'julialang',\n 'dart-code',\n 'flutter',\n 'svelte',\n 'vue',\n 'angular',\n 'astro-build',\n\n // Major tool vendors (verified)\n 'jetbrains',\n 'docker',\n 'mongodb',\n 'prisma',\n 'atlassian',\n 'gitlab',\n 'sourcegraph',\n 'snyk-security',\n 'sonarqube',\n 'datadog',\n\n // Popular extension vendors (verified)\n 'davidanson', // markdownlint\n 'esbenp', // Prettier\n 'dbaeumer', // ESLint\n 'eamodio', // GitLens\n 'streetsidesoftware', // Code Spell Checker\n 'editorconfig',\n 'christian-kohler', // Path Intellisense\n 'visualstudioexptteam', // IntelliCode\n 'bierner', // Markdown Preview\n 'jock', // SVG Viewer\n 'pkief', // Material Icon Theme\n 'zhuangtongfa', // One Dark Pro\n 'mechatroner', // Rainbow CSV\n];\n\n/**\n * Check if a publisher is verified on the marketplace.\n */\nexport function isVerifiedPublisher(publisher: string): boolean {\n const normalized = publisher.toLowerCase();\n return VERIFIED_PUBLISHERS.some((p) => normalized === p.toLowerCase());\n}\n","/**\n * List of popular extensions with high download counts.\n *\n * Extensions with millions of downloads have been vetted by the community\n * through widespread usage. Supply chain attacks on these would be extremely\n * visible and risky for attackers.\n *\n * Threshold tiers:\n * - 10M+ downloads: Highest trust (downgrade by 2 severity levels)\n * - 1M+ downloads: High trust (downgrade by 1 severity level)\n *\n * Note: This data is manually maintained. In the future, this could be\n * fetched from the marketplace API and cached locally.\n *\n * Last updated: 2026-02\n */\n\nexport interface PopularExtension {\n id: string;\n downloads: number;\n tier: 'mega' | 'popular'; // mega: 10M+, popular: 1M+\n}\n\n/**\n * Extensions with 10M+ downloads (mega popular)\n */\nexport const MEGA_POPULAR_EXTENSIONS: PopularExtension[] = [\n // Python ecosystem\n { id: 'ms-python.python', downloads: 120_000_000, tier: 'mega' },\n { id: 'ms-python.vscode-pylance', downloads: 80_000_000, tier: 'mega' },\n\n // C/C++\n { id: 'ms-vscode.cpptools', downloads: 60_000_000, tier: 'mega' },\n\n // GitHub Copilot\n { id: 'github.copilot', downloads: 50_000_000, tier: 'mega' },\n { id: 'github.copilot-chat', downloads: 30_000_000, tier: 'mega' },\n\n // ESLint & Prettier\n { id: 'dbaeumer.vscode-eslint', downloads: 45_000_000, tier: 'mega' },\n { id: 'esbenp.prettier-vscode', downloads: 50_000_000, tier: 'mega' },\n\n // Live Server\n { id: 'ritwickdey.liveserver', downloads: 60_000_000, tier: 'mega' },\n\n // GitLens\n { id: 'eamodio.gitlens', downloads: 40_000_000, tier: 'mega' },\n\n // Docker\n { id: 'ms-azuretools.vscode-docker', downloads: 35_000_000, tier: 'mega' },\n\n // Remote Development\n { id: 'ms-vscode-remote.remote-ssh', downloads: 25_000_000, tier: 'mega' },\n { id: 'ms-vscode-remote.remote-containers', downloads: 20_000_000, tier: 'mega' },\n { id: 'ms-vscode-remote.remote-wsl', downloads: 20_000_000, tier: 'mega' },\n\n // IntelliCode\n { id: 'visualstudioexptteam.vscodeintellicode', downloads: 40_000_000, tier: 'mega' },\n\n // Path Intellisense\n { id: 'christian-kohler.path-intellisense', downloads: 20_000_000, tier: 'mega' },\n\n // Material Icon Theme\n { id: 'pkief.material-icon-theme', downloads: 30_000_000, tier: 'mega' },\n\n // One Dark Pro\n { id: 'zhuangtongfa.material-theme', downloads: 15_000_000, tier: 'mega' },\n\n // Bracket Pair Colorizer (now built-in but still installed)\n { id: 'coenraads.bracket-pair-colorizer-2', downloads: 12_000_000, tier: 'mega' },\n\n // Code Runner\n { id: 'formulahendry.code-runner', downloads: 20_000_000, tier: 'mega' },\n\n // Auto Rename Tag\n { id: 'formulahendry.auto-rename-tag', downloads: 18_000_000, tier: 'mega' },\n\n // Code Spell Checker\n { id: 'streetsidesoftware.code-spell-checker', downloads: 15_000_000, tier: 'mega' },\n\n // Markdown All in One\n { id: 'yzhang.markdown-all-in-one', downloads: 12_000_000, tier: 'mega' },\n\n // Debugger for Chrome (deprecated but still installed)\n { id: 'msjsdiag.debugger-for-chrome', downloads: 25_000_000, tier: 'mega' },\n\n // Go\n { id: 'golang.go', downloads: 15_000_000, tier: 'mega' },\n\n // Java\n { id: 'redhat.java', downloads: 20_000_000, tier: 'mega' },\n { id: 'vscjava.vscode-java-debug', downloads: 15_000_000, tier: 'mega' },\n { id: 'vscjava.vscode-java-pack', downloads: 18_000_000, tier: 'mega' },\n\n // C#\n { id: 'ms-dotnettools.csharp', downloads: 25_000_000, tier: 'mega' },\n];\n\n/**\n * Extensions with 1M-10M downloads (popular)\n */\nexport const POPULAR_EXTENSIONS: PopularExtension[] = [\n // REST Clients\n { id: 'humao.rest-client', downloads: 5_000_000, tier: 'popular' },\n { id: 'rangav.vscode-thunder-client', downloads: 3_000_000, tier: 'popular' },\n\n // Database\n { id: 'mtxr.sqltools', downloads: 4_000_000, tier: 'popular' },\n { id: 'cweijan.vscode-database-client2', downloads: 2_000_000, tier: 'popular' },\n\n // Jupyter\n { id: 'ms-toolsai.jupyter', downloads: 8_000_000, tier: 'popular' },\n { id: 'ms-toolsai.jupyter-keymap', downloads: 5_000_000, tier: 'popular' },\n\n // Kubernetes\n { id: 'ms-kubernetes-tools.vscode-kubernetes-tools', downloads: 4_000_000, tier: 'popular' },\n\n // Vue / React / Angular\n { id: 'vue.volar', downloads: 8_000_000, tier: 'popular' },\n { id: 'dsznajder.es7-react-js-snippets', downloads: 9_000_000, tier: 'popular' },\n { id: 'angular.ng-template', downloads: 5_000_000, tier: 'popular' },\n\n // Svelte\n { id: 'svelte.svelte-vscode', downloads: 3_000_000, tier: 'popular' },\n\n // Astro\n { id: 'astro-build.astro-vscode', downloads: 2_000_000, tier: 'popular' },\n\n // Tailwind CSS\n { id: 'bradlc.vscode-tailwindcss', downloads: 8_000_000, tier: 'popular' },\n\n // YAML\n { id: 'redhat.vscode-yaml', downloads: 9_000_000, tier: 'popular' },\n\n // XML\n { id: 'redhat.vscode-xml', downloads: 6_000_000, tier: 'popular' },\n\n // Rust\n { id: 'rust-lang.rust-analyzer', downloads: 5_000_000, tier: 'popular' },\n\n // PowerShell\n { id: 'ms-vscode.powershell', downloads: 8_000_000, tier: 'popular' },\n\n // Terraform\n { id: 'hashicorp.terraform', downloads: 9_000_000, tier: 'popular' },\n\n // TODO Highlight\n { id: 'wayou.vscode-todo-highlight', downloads: 6_000_000, tier: 'popular' },\n\n // Bookmarks\n { id: 'alefragnani.bookmarks', downloads: 5_000_000, tier: 'popular' },\n\n // Project Manager\n { id: 'alefragnani.project-manager', downloads: 4_000_000, tier: 'popular' },\n\n // Rainbow CSV\n { id: 'mechatroner.rainbow-csv', downloads: 4_000_000, tier: 'popular' },\n\n // Markdown Preview\n { id: 'bierner.markdown-preview-github-styles', downloads: 3_000_000, tier: 'popular' },\n\n // markdownlint\n { id: 'davidanson.vscode-markdownlint', downloads: 6_000_000, tier: 'popular' },\n\n // Error Lens\n { id: 'usernamehw.errorlens', downloads: 5_000_000, tier: 'popular' },\n\n // Playwright\n { id: 'ms-playwright.playwright', downloads: 2_000_000, tier: 'popular' },\n\n // Jest\n { id: 'orta.vscode-jest', downloads: 3_000_000, tier: 'popular' },\n\n // Swagger / OpenAPI\n { id: 'arjun.swagger-viewer', downloads: 2_000_000, tier: 'popular' },\n\n // Figma\n { id: 'figma.figma-vscode-extension', downloads: 1_000_000, tier: 'popular' },\n\n // Atlassian\n { id: 'atlassian.atlascode', downloads: 2_000_000, tier: 'popular' },\n];\n\n/**\n * All popular extensions combined\n */\nexport const ALL_POPULAR_EXTENSIONS: PopularExtension[] = [\n ...MEGA_POPULAR_EXTENSIONS,\n ...POPULAR_EXTENSIONS,\n];\n\n/**\n * Get popularity tier for an extension.\n * Returns null if not in the popular extensions list.\n */\nexport function getPopularityTier(extensionId: string): 'mega' | 'popular' | null {\n const normalized = extensionId.toLowerCase();\n const ext = ALL_POPULAR_EXTENSIONS.find((e) => e.id.toLowerCase() === normalized);\n return ext?.tier ?? null;\n}\n\n/**\n * Check if an extension is mega popular (10M+ downloads)\n */\nexport function isMegaPopular(extensionId: string): boolean {\n return getPopularityTier(extensionId) === 'mega';\n}\n\n/**\n * Check if an extension is popular (1M+ downloads)\n */\nexport function isPopular(extensionId: string): boolean {\n return getPopularityTier(extensionId) !== null;\n}\n","import type { Finding, Severity } from '../types/index.js';\nimport type { ExtensionCategory } from '../scanner/extension-categorizer.js';\nimport { isTrustedPublisher, isTrustedExtension } from '../data/trusted-publishers.js';\nimport { isVerifiedPublisher } from '../data/verified-publishers.js';\nimport { getPopularityTier } from '../data/popular-extensions.js';\n\n/**\n * Severity one level below the given severity.\n * Used to downgrade findings that match expected behavior for the category.\n */\nconst DOWNGRADE_MAP: Record<Severity, Severity> = {\n critical: 'medium',\n high: 'low',\n medium: 'info',\n low: 'info',\n info: 'info',\n};\n\n/**\n * Rule IDs and matched patterns that are expected (not suspicious) for each category.\n * When a finding matches, its severity is downgraded.\n */\ninterface ExpectedBehavior {\n ruleIds?: string[];\n matchedPatterns?: string[];\n categories?: string[];\n}\n\n/**\n * For each extension category, define which rule findings are considered\n * expected/legitimate behavior and should be downgraded.\n */\nconst EXPECTED_BEHAVIORS: Partial<Record<ExtensionCategory, ExpectedBehavior[]>> = {\n 'ai-assistant': [\n {\n // AI tools legitimately use child_process, eval for code execution\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n 'eval',\n 'Function-constructor',\n 'dynamic-require',\n ],\n },\n {\n // AI tools legitimately make network requests\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['dynamic-url', 'unusual-port'],\n },\n {\n // AI tools often read .env for API keys\n ruleIds: ['EG-CRIT-003'],\n matchedPatterns: ['env-file'],\n },\n {\n // AI tools collect system info for telemetry / model context\n // This includes os.hostname, os.platform, os.userInfo, process.env, etc.\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // AI tools may have obfuscated/minified bundled code\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n\n theme: [\n {\n // Theme extensions with bundled JS may trigger obfuscation (false positive)\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n\n language: [\n {\n // Grammar extensions often have high-entropy bundled code or regex-heavy files\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n {\n // Grammar files use words like \"token\", \"secret\" in syntax definitions\n ruleIds: ['EG-HIGH-006'],\n matchedPatterns: ['generic-secret'],\n },\n ],\n\n scm: [\n {\n // SCM extensions legitimately access git credentials\n ruleIds: ['EG-CRIT-003'],\n matchedPatterns: ['git-credentials'],\n },\n {\n // SCM extensions may spawn git processes\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n ],\n },\n ],\n\n debugger: [\n {\n // Debuggers legitimately spawn processes\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n ],\n },\n {\n // Debuggers may use dynamic require for adapter loading\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: ['dynamic-require'],\n },\n ],\n\n linter: [\n {\n // Linters legitimately spawn processes (eslint, prettier, etc.)\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n ],\n },\n ],\n\n 'language-support': [\n {\n // Language servers spawn interpreters/compilers (python, go, rustc, javac)\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n 'dynamic-require',\n ],\n },\n {\n // Language servers may collect system info for environment detection\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // Language servers may have bundled code with high entropy\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n {\n // Language servers may make network requests for package management\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['dynamic-url'],\n },\n ],\n\n 'developer-tools': [\n {\n // Code runners spawn processes to execute code (python, node, bash, etc.)\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n 'eval',\n 'Function-constructor',\n ],\n },\n {\n // REST clients, API testers make network requests by design\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['dynamic-url', 'http-to-ip', 'unusual-port'],\n },\n {\n // Live servers spawn HTTP servers on various ports\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['unusual-port'],\n },\n {\n // Developer tools may collect system info for environment detection\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // Developer tools may have bundled code with high entropy\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n\n 'remote-development': [\n {\n // Remote extensions spawn SSH, docker, WSL processes\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n ],\n },\n {\n // Remote extensions make network connections by design\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['dynamic-url', 'http-to-ip', 'unusual-port'],\n },\n {\n // Remote extensions collect system info for environment detection\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // Remote extensions may access SSH keys and credentials legitimately\n ruleIds: ['EG-CRIT-003'],\n matchedPatterns: ['ssh-keys', 'ssh-config'],\n },\n {\n // Remote extensions may have bundled code\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n\n testing: [\n {\n // Test runners spawn test processes\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n ],\n },\n {\n // Test runners may collect system info for environment detection\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // Test runners may have bundled code\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n\n notebook: [\n {\n // Notebook extensions spawn kernels (Python, Julia, etc.)\n ruleIds: ['EG-CRIT-002'],\n matchedPatterns: [\n 'child_process-exec',\n 'child_process-execSync',\n 'child_process-spawn-shell',\n 'dynamic-require',\n ],\n },\n {\n // Notebook extensions make network connections for package management\n ruleIds: ['EG-HIGH-002'],\n matchedPatterns: ['dynamic-url', 'unusual-port'],\n },\n {\n // Notebook extensions collect system info for environment detection\n ruleIds: ['EG-CRIT-001'],\n },\n {\n // Notebook extensions may read environment files for kernel config\n ruleIds: ['EG-CRIT-003'],\n matchedPatterns: ['env-file'],\n },\n {\n // Notebook extensions may have bundled code\n ruleIds: ['EG-HIGH-001'],\n matchedPatterns: ['high-entropy', 'large-base64'],\n },\n ],\n};\n\n/**\n * Check if a finding matches an expected behavior definition.\n */\nfunction matchesExpectedBehavior(finding: Finding, behavior: ExpectedBehavior): boolean {\n // Must match rule ID if specified\n if (behavior.ruleIds && !behavior.ruleIds.includes(finding.ruleId)) {\n return false;\n }\n\n // If matchedPatterns specified, the finding's evidence must match one\n if (behavior.matchedPatterns && behavior.matchedPatterns.length > 0) {\n const pattern = finding.evidence.matchedPattern ?? '';\n if (!behavior.matchedPatterns.some((p) => pattern.includes(p))) {\n return false;\n }\n }\n\n // If categories specified, the finding's category must match\n if (behavior.categories && behavior.categories.length > 0) {\n if (!behavior.categories.includes(finding.category)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Options for adjusting findings.\n */\nexport interface AdjustFindingsOptions {\n /** Publisher name for soft trust check */\n publisher?: string;\n /** Full extension ID (publisher.name) for soft trust check */\n extensionId?: string;\n /** Skip soft trust adjustments (strict mode) */\n strictMode?: boolean;\n /** Map of file paths to file contents for bundle detection */\n files?: Map<string, string>;\n}\n\n/**\n * Two-level downgrade map (for mega popular extensions)\n */\nconst DOUBLE_DOWNGRADE_MAP: Record<Severity, Severity> = {\n critical: 'low',\n high: 'info',\n medium: 'info',\n low: 'info',\n info: 'info',\n};\n\n/**\n * Adjust findings based on the extension's inferred category and trust status.\n *\n * Four layers of adjustment:\n * 1. Category-based: Expected behaviors for extension type (e.g., AI tools use network)\n * 2. Soft Trust: Trusted publishers get an additional severity downgrade\n * 3. Verified Publisher: Verified publishers on marketplace get severity downgrade\n * 4. Popularity: Extensions with 10M+ downloads get double downgrade, 1M+ get single\n *\n * Returns a new array with adjusted findings (original array is not mutated).\n */\nexport function adjustFindings(\n findings: Finding[],\n category: ExtensionCategory,\n options: AdjustFindingsOptions = {}\n): Finding[] {\n const { publisher, extensionId, strictMode = false } = options;\n const behaviors = EXPECTED_BEHAVIORS[category];\n\n // Check trust levels (only if not in strict mode)\n const isTrusted =\n !strictMode &&\n ((publisher && isTrustedPublisher(publisher)) ||\n (extensionId && isTrustedExtension(extensionId)));\n\n const isVerified = !strictMode && publisher && isVerifiedPublisher(publisher);\n\n const popularityTier = !strictMode && extensionId ? getPopularityTier(extensionId) : null;\n\n return findings.map((finding) => {\n let adjustedFinding = finding;\n let reasons: string[] = [];\n\n // Layer 1: Category-based adjustment\n if (behaviors && behaviors.length > 0) {\n for (const behavior of behaviors) {\n if (matchesExpectedBehavior(finding, behavior)) {\n const downgraded = DOWNGRADE_MAP[adjustedFinding.severity];\n adjustedFinding = {\n ...adjustedFinding,\n severity: downgraded,\n };\n reasons.push(`expected behavior for ${category} extension`);\n break;\n }\n }\n }\n\n // Layer 2: Soft Trust adjustment (additional downgrade for trusted publishers)\n if (isTrusted && adjustedFinding.severity !== 'info') {\n const downgraded = DOWNGRADE_MAP[adjustedFinding.severity];\n adjustedFinding = {\n ...adjustedFinding,\n severity: downgraded,\n };\n reasons.push(`trusted publisher`);\n }\n\n // Layer 3: Verified Publisher adjustment (if not already trusted)\n if (!isTrusted && isVerified && adjustedFinding.severity !== 'info') {\n const downgraded = DOWNGRADE_MAP[adjustedFinding.severity];\n adjustedFinding = {\n ...adjustedFinding,\n severity: downgraded,\n };\n reasons.push(`verified publisher`);\n }\n\n // Layer 4: Popularity-based adjustment\n if (popularityTier && adjustedFinding.severity !== 'info') {\n if (popularityTier === 'mega') {\n // 10M+ downloads: double downgrade\n const downgraded = DOUBLE_DOWNGRADE_MAP[adjustedFinding.severity];\n adjustedFinding = {\n ...adjustedFinding,\n severity: downgraded,\n };\n reasons.push(`mega popular (10M+ downloads)`);\n } else if (popularityTier === 'popular') {\n // 1M+ downloads: single downgrade\n const downgraded = DOWNGRADE_MAP[adjustedFinding.severity];\n adjustedFinding = {\n ...adjustedFinding,\n severity: downgraded,\n };\n reasons.push(`popular (1M+ downloads)`);\n }\n }\n\n // Add reason to description if any adjustments were made\n if (reasons.length > 0) {\n adjustedFinding = {\n ...adjustedFinding,\n description: `${finding.description} [Downgraded: ${reasons.join(' + ')}]`,\n };\n }\n\n return adjustedFinding;\n });\n}\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\nconst SYSTEM_INFO_PATTERNS = [\n { name: 'os.hostname', pattern: /os\\.hostname\\s*\\(\\)/g },\n { name: 'os.userInfo', pattern: /os\\.userInfo\\s*\\(\\)/g },\n { name: 'os.platform', pattern: /os\\.platform\\s*\\(\\)/g },\n { name: 'os.arch', pattern: /os\\.arch\\s*\\(\\)/g },\n { name: 'os.networkInterfaces', pattern: /os\\.networkInterfaces\\s*\\(\\)/g },\n { name: 'os.cpus', pattern: /os\\.cpus\\s*\\(\\)/g },\n { name: 'os.homedir', pattern: /os\\.homedir\\s*\\(\\)/g },\n { name: 'process.env', pattern: /process\\.env(?:\\[|\\.)/g },\n];\n\nconst HTTP_TO_IP_PATTERN =\n /(?:https?\\.request|fetch|axios\\.(?:get|post|put|request))\\s*\\(\\s*['\"`]https?:\\/\\/\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/g;\n\nexport const critDataExfiltration: DetectionRule = {\n id: 'EG-CRIT-001',\n name: 'Data Exfiltration Pattern',\n description:\n 'Detects code that collects system info and sends it to external servers via IP address',\n severity: 'critical',\n category: 'data-exfiltration',\n mitreAttackId: 'T1041',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const lines = content.split('\\n');\n\n // Check for system info collection\n let hasSystemInfo = false;\n let systemInfoPatternName = '';\n let systemInfoLine = 0;\n\n for (const { name, pattern } of SYSTEM_INFO_PATTERNS) {\n pattern.lastIndex = 0;\n const match = pattern.exec(content);\n if (match) {\n hasSystemInfo = true;\n systemInfoPatternName = name;\n systemInfoLine = content.slice(0, match.index).split('\\n').length;\n break;\n }\n }\n\n // Check for HTTP to IP\n HTTP_TO_IP_PATTERN.lastIndex = 0;\n const httpMatch = HTTP_TO_IP_PATTERN.exec(content);\n\n if (hasSystemInfo && httpMatch) {\n const httpToIpLine = content.slice(0, httpMatch.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber: httpToIpLine,\n lineContent: lines[httpToIpLine - 1]?.trim(),\n matchedPattern: `${systemInfoPatternName} + http-to-ip`,\n snippet: `System info (${systemInfoPatternName}) collected at line ${systemInfoLine}, sent to IP at line ${httpToIpLine}`,\n });\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\nconst DANGEROUS_PATTERNS = [\n { name: 'eval', pattern: /\\beval\\s*\\(/g },\n { name: 'Function-constructor', pattern: /new\\s+Function\\s*\\(/g },\n {\n name: 'child_process-exec',\n pattern: /(?:require\\s*\\(\\s*['\"]child_process['\"]\\s*\\)|child_process)\\.exec\\s*\\(/g,\n },\n {\n name: 'child_process-execSync',\n pattern: /(?:require\\s*\\(\\s*['\"]child_process['\"]\\s*\\)|child_process)\\.execSync\\s*\\(/g,\n },\n { name: 'child_process-spawn-shell', pattern: /\\.spawn\\s*\\([^)]*\\{[^}]*shell\\s*:\\s*true/g },\n { name: 'vm-runInContext', pattern: /vm\\.run(?:InContext|InNewContext|InThisContext)\\s*\\(/g },\n { name: 'vm-Script', pattern: /new\\s+vm\\.Script\\s*\\(/g },\n];\n\nconst DYNAMIC_REQUIRE = /require\\s*\\(\\s*(?:[^'\"`\\s)]|`[^`]*\\$\\{)/g;\n\nexport const critRemoteExecution: DetectionRule = {\n id: 'EG-CRIT-002',\n name: 'Remote Code Execution',\n description: 'Detects dangerous code execution patterns like eval, exec, or dynamic require',\n severity: 'critical',\n category: 'remote-code-execution',\n mitreAttackId: 'T1059',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const lines = content.split('\\n');\n\n for (const { name, pattern } of DANGEROUS_PATTERNS) {\n pattern.lastIndex = 0;\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lines[lineNumber - 1]?.trim(),\n matchedPattern: name,\n snippet: match[0],\n });\n }\n }\n\n DYNAMIC_REQUIRE.lastIndex = 0;\n let match;\n while ((match = DYNAMIC_REQUIRE.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lines[lineNumber - 1]?.trim(),\n matchedPattern: 'dynamic-require',\n snippet: match[0],\n });\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\nconst SENSITIVE_PATHS = [\n {\n name: 'ssh-keys',\n pattern:\n /['\"`][^'\"`]*\\.ssh[/\\\\](?:id_rsa|id_ed25519|id_ecdsa|known_hosts|config|authorized_keys)[^'\"`]*['\"`]/gi,\n },\n { name: 'gnupg', pattern: /['\"`][^'\"`]*\\.gnupg[/\\\\][^'\"`]*['\"`]/gi },\n { name: 'aws-credentials', pattern: /['\"`][^'\"`]*\\.aws[/\\\\]credentials[^'\"`]*['\"`]/gi },\n { name: 'azure-config', pattern: /['\"`][^'\"`]*\\.azure[/\\\\][^'\"`]*['\"`]/gi },\n { name: 'kube-config', pattern: /['\"`][^'\"`]*\\.kube[/\\\\]config[^'\"`]*['\"`]/gi },\n { name: 'git-credentials', pattern: /['\"`][^'\"`]*\\.git-credentials[^'\"`]*['\"`]/gi },\n { name: 'env-file', pattern: /['\"`][^'\"`]*\\.env(?:\\.\\w+)?['\"`]/gi },\n { name: 'npmrc', pattern: /['\"`][^'\"`]*\\.npmrc[^'\"`]*['\"`]/gi },\n { name: 'docker-config', pattern: /['\"`][^'\"`]*\\.docker[/\\\\]config\\.json[^'\"`]*['\"`]/gi },\n { name: 'netrc', pattern: /['\"`][^'\"`]*\\.netrc[^'\"`]*['\"`]/gi },\n];\n\nconst FILE_READ_CONTEXT =\n /(?:readFile|readFileSync|createReadStream|access|accessSync|exists|existsSync|stat|statSync|open|openSync)/;\n\nexport const critCredentialAccess: DetectionRule = {\n id: 'EG-CRIT-003',\n name: 'Credential File Access',\n description:\n 'Detects attempts to read sensitive credential files like SSH keys, AWS credentials, or .env files',\n severity: 'critical',\n category: 'credential-theft',\n mitreAttackId: 'T1552.004',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const lines = content.split('\\n');\n\n for (const { name, pattern } of SENSITIVE_PATHS) {\n pattern.lastIndex = 0;\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const startIndex = Math.max(0, match.index - 200);\n const endIndex = Math.min(content.length, match.index + match[0].length + 200);\n const context = content.slice(startIndex, endIndex);\n\n if (FILE_READ_CONTEXT.test(context)) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lines[lineNumber - 1]?.trim(),\n matchedPattern: name,\n snippet: match[0],\n });\n }\n }\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\n// HTTP requests to IP addresses instead of domains\nconst HTTP_TO_IP =\n /(?:fetch|axios(?:\\.(?:get|post|put|delete|request))?|https?\\.(?:get|post|request)|XMLHttpRequest)\\s*\\([^)]*['\"`]https?:\\/\\/\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/g;\n\n// Dynamic URL construction (template literals or concatenation)\nconst DYNAMIC_URL =\n /(?:fetch|axios|https?\\.request)\\s*\\(\\s*(?:`[^`]*\\$\\{|['\"][^'\"]*['\"]\\s*\\+\\s*\\w)/g;\n\n// WebSocket connections to IP addresses\nconst WEBSOCKET_TO_IP = /new\\s+WebSocket\\s*\\(\\s*['\"`]wss?:\\/\\/\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/g;\n\n// Unusual ports\nconst UNUSUAL_PORTS = /['\"`]https?:\\/\\/[^'\"`:]+:(?!443|80|8080|3000|8443|5000)[0-9]{2,5}/g;\n\nexport const highSuspiciousNetwork: DetectionRule = {\n id: 'EG-HIGH-002',\n name: 'Suspicious Network Activity',\n description: 'Detects network requests to IP addresses, dynamic URLs, or unusual ports',\n severity: 'high',\n category: 'suspicious-network',\n mitreAttackId: 'T1071',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const lines = content.split('\\n');\n const patterns = [\n { pattern: HTTP_TO_IP, name: 'http-to-ip' },\n { pattern: DYNAMIC_URL, name: 'dynamic-url' },\n { pattern: WEBSOCKET_TO_IP, name: 'websocket-to-ip' },\n { pattern: UNUSUAL_PORTS, name: 'unusual-port' },\n ];\n\n for (const { pattern, name } of patterns) {\n pattern.lastIndex = 0;\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lines[lineNumber - 1]?.trim(),\n matchedPattern: name,\n snippet: match[0].slice(0, 100),\n });\n }\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\nconst MIN_BASE64_LENGTH = 100;\nconst BASE64_PATTERN = /['\"`]([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?['\"`]/g;\nconst HEX_PATTERN = /(?:\\\\x[0-9a-fA-F]{2}){10,}/g;\nconst CHAR_CODE_PATTERN = /String\\.fromCharCode\\s*\\(\\s*(?:\\d+\\s*,?\\s*){5,}\\)/g;\nconst UNICODE_ESCAPE_PATTERN = /(?:\\\\u[0-9a-fA-F]{4}){10,}/g;\n\n// Bundled/minified files: single large JS in dist/ or out/ directory, or well-known bundler output\nconst BUNDLED_FILE_PATTERN = /(?:^|\\/)(?:dist|out|build|bundle)\\//;\nconst BUNDLED_FILE_SIZE_THRESHOLD = 100 * 1024; // 100KB — typical bundle size\n\nfunction calculateEntropy(str: string): number {\n const len = str.length;\n if (len === 0) return 0;\n const freq: Record<string, number> = {};\n for (const char of str) {\n freq[char] = (freq[char] || 0) + 1;\n }\n let entropy = 0;\n for (const count of Object.values(freq)) {\n const p = count / len;\n entropy -= p * Math.log2(p);\n }\n return entropy;\n}\n\nexport const highObfuscatedCode: DetectionRule = {\n id: 'EG-HIGH-001',\n name: 'Code Obfuscation Detected',\n description: 'Detects heavily obfuscated code patterns that may hide malicious behavior',\n severity: 'high',\n category: 'code-obfuscation',\n mitreAttackId: 'T1027',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n if (!filePath.endsWith('.js') && !filePath.endsWith('.ts')) {\n continue;\n }\n\n const lines = content.split('\\n');\n\n // Check for large base64 strings\n BASE64_PATTERN.lastIndex = 0;\n let match;\n while ((match = BASE64_PATTERN.exec(content)) !== null) {\n const base64Content = match[0].slice(1, -1);\n if (base64Content.length >= MIN_BASE64_LENGTH) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: (lines[lineNumber - 1]?.trim() || '').slice(0, 80) + '...',\n matchedPattern: 'large-base64',\n snippet: `Base64 string of ${base64Content.length} characters`,\n });\n }\n }\n\n // Check for hex-encoded strings\n HEX_PATTERN.lastIndex = 0;\n while ((match = HEX_PATTERN.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: (lines[lineNumber - 1]?.trim() || '').slice(0, 80) + '...',\n matchedPattern: 'hex-encoded',\n snippet: match[0].slice(0, 50) + '...',\n });\n }\n\n // Check for String.fromCharCode abuse\n CHAR_CODE_PATTERN.lastIndex = 0;\n while ((match = CHAR_CODE_PATTERN.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lines[lineNumber - 1]?.trim(),\n matchedPattern: 'charcode-obfuscation',\n snippet: match[0].slice(0, 80),\n });\n }\n\n // Check for unicode escape sequences\n UNICODE_ESCAPE_PATTERN.lastIndex = 0;\n while ((match = UNICODE_ESCAPE_PATTERN.exec(content)) !== null) {\n const lineNumber = content.slice(0, match.index).split('\\n').length;\n evidences.push({\n filePath,\n lineNumber,\n lineContent: (lines[lineNumber - 1]?.trim() || '').slice(0, 80) + '...',\n matchedPattern: 'unicode-escape',\n snippet: match[0].slice(0, 50) + '...',\n });\n }\n\n // Check overall file entropy for large files\n // Skip bundled/minified files (>100KB in dist/out/build dirs) — they naturally have high entropy\n const isBundled =\n BUNDLED_FILE_PATTERN.test(filePath) && content.length > BUNDLED_FILE_SIZE_THRESHOLD;\n\n if (!isBundled && content.length > 5000) {\n const entropy = calculateEntropy(content);\n // Threshold raised from 5.8 to 6.2 — bundled JS with regex-heavy content\n // (grammar definitions, URL patterns) routinely hits 5.8-6.0\n if (entropy > 6.2) {\n evidences.push({\n filePath,\n lineNumber: 1,\n matchedPattern: 'high-entropy',\n snippet: `File entropy: ${entropy.toFixed(2)} (threshold: 6.2)`,\n });\n }\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\n// Minimum length for a value to be considered a potential secret\nconst MIN_SECRET_LENGTH = 8;\n\n// Minimum entropy for generic-secret values — filters out natural language and config values\nconst MIN_GENERIC_SECRET_ENTROPY = 3.0;\n\n// Patterns that indicate placeholder values (false positives)\nconst PLACEHOLDER_PATTERNS = [\n /^your[_-]?/i,\n /^<[^>]+>$/,\n /^replace[_-]?me$/i,\n /^xxx+$/i,\n /^x{3,}[_-]x{3,}/i,\n /^todo$/i,\n /^fixme$/i,\n /^example$/i,\n /^placeholder$/i,\n /^changeme$/i,\n /^\\*+$/,\n /^\\.+$/,\n /^test$/i,\n /^demo$/i,\n];\n\n// Common false-positive values for generic-secret pattern\n// These are legitimate config/code patterns, not actual secrets\nconst FALSE_POSITIVE_VALUES = [\n /^(?:true|false|null|undefined|none)$/i,\n /^(?:string|number|boolean|object|array|function)$/i,\n /^(?:keyword|identifier|operator|punctuation|comment|variable|constant)$/i, // TextMate token types\n /^(?:bearer|basic|digest)\\s/i, // Auth scheme names, not actual tokens\n /^(?:process\\.env|os\\.environ)/i, // Env access patterns\n /^https?:\\/\\//i, // URLs\n /^\\$\\{/, // Template literals\n /^%[sd]/, // Format strings\n];\n\n// File patterns to exclude (test files, examples, docs)\nconst EXCLUDED_FILE_PATTERNS = [\n /\\.test\\.[jt]sx?$/,\n /\\.spec\\.[jt]sx?$/,\n /__tests__\\//,\n /(?:^|\\/)test\\//,\n /(?:^|\\/)tests\\//,\n /(?:^|\\/)examples?\\//,\n /(?:^|\\/)demo\\//,\n /\\.md$/,\n /\\.txt$/,\n /\\.rst$/,\n];\n\n// Code file extensions to scan\nconst CODE_FILE_EXTENSIONS = ['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs'];\n\ninterface SecretPattern {\n name: string;\n pattern: RegExp;\n matchGroup?: number;\n}\n\nconst SECRET_PATTERNS: SecretPattern[] = [\n // AWS Access Key ID (starts with AKIA)\n {\n name: 'aws-access-key',\n pattern: /AKIA[0-9A-Z]{16}/g,\n },\n // AWS Secret Access Key\n {\n name: 'aws-secret-key',\n pattern:\n /(?:aws[_-]?secret(?:[_-]?access)?[_-]?key|secret[_-]?access[_-]?key)\\s*[:=]\\s*['\"`]([A-Za-z0-9/+=]{40})['\"`]/gi,\n matchGroup: 1,\n },\n // GitHub tokens (ghp_, gho_, ghs_, ghr_)\n {\n name: 'github-token',\n pattern: /gh[pors]_[A-Za-z0-9]{36,}/g,\n },\n // Slack tokens (xoxb-, xoxp-, xoxa-, xoxr-)\n {\n name: 'slack-token',\n pattern: /xox[bpar]-[0-9]+-[0-9]+-[A-Za-z0-9]+/g,\n },\n // Private keys\n {\n name: 'private-key',\n pattern: /-----BEGIN\\s+(?:RSA\\s+|EC\\s+|DSA\\s+|OPENSSH\\s+)?PRIVATE\\s+KEY-----/g,\n },\n // Bearer tokens (JWT format)\n {\n name: 'bearer-token',\n pattern: /Bearer\\s+([A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+)/g,\n matchGroup: 1,\n },\n // API key assignments\n {\n name: 'api-key',\n pattern: /(?:api[_-]?key|apikey)\\s*[:=]\\s*['\"`]([A-Za-z0-9_-]{16,})['\"`]/gi,\n matchGroup: 1,\n },\n // Generic secrets (password, secret, token, passwd, pwd)\n {\n name: 'generic-secret',\n pattern: /(?:password|passwd|pwd|secret|token)\\s*[:=]\\s*['\"`]([^'\"`]{8,})['\"`]/gi,\n matchGroup: 1,\n },\n];\n\nfunction isCodeFile(filePath: string): boolean {\n return CODE_FILE_EXTENSIONS.some((ext) => filePath.endsWith(ext));\n}\n\nfunction isExcludedFile(filePath: string): boolean {\n return EXCLUDED_FILE_PATTERNS.some((pattern) => pattern.test(filePath));\n}\n\nfunction isPlaceholder(value: string): boolean {\n return PLACEHOLDER_PATTERNS.some((pattern) => pattern.test(value));\n}\n\nfunction isFalsePositiveValue(value: string): boolean {\n return FALSE_POSITIVE_VALUES.some((pattern) => pattern.test(value));\n}\n\nfunction calculateSecretEntropy(str: string): number {\n const len = str.length;\n if (len === 0) return 0;\n const freq: Record<string, number> = {};\n for (const char of str) {\n freq[char] = (freq[char] || 0) + 1;\n }\n let entropy = 0;\n for (const count of Object.values(freq)) {\n const p = count / len;\n entropy -= p * Math.log2(p);\n }\n return entropy;\n}\n\nfunction isInComment(content: string, matchIndex: number): boolean {\n // Find the start of the line containing the match\n const lineStart = content.lastIndexOf('\\n', matchIndex) + 1;\n const lineContent = content.slice(lineStart, matchIndex);\n\n // Check for single-line comment\n if (lineContent.includes('//')) {\n return true;\n }\n\n // Check for block comment - look for /* before the match without a closing */\n const beforeMatch = content.slice(0, matchIndex);\n const lastBlockStart = beforeMatch.lastIndexOf('/*');\n const lastBlockEnd = beforeMatch.lastIndexOf('*/');\n\n if (lastBlockStart > lastBlockEnd) {\n return true;\n }\n\n return false;\n}\n\nfunction getLineNumber(content: string, index: number): number {\n return content.slice(0, index).split('\\n').length;\n}\n\nexport const highHardcodedSecret: DetectionRule = {\n id: 'EG-HIGH-006',\n name: 'Hardcoded Secrets',\n description: 'Detects hardcoded API keys, tokens, passwords, and other secrets in code',\n severity: 'high',\n category: 'hardcoded-secret',\n mitreAttackId: 'T1552.001',\n enabled: true,\n\n detect(files: Map<string, string>, _manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n for (const [filePath, content] of files) {\n // Skip non-code files\n if (!isCodeFile(filePath)) {\n continue;\n }\n\n // Skip test/example files\n if (isExcludedFile(filePath)) {\n continue;\n }\n\n // Skip empty files\n if (!content || content.trim().length === 0) {\n continue;\n }\n\n const lines = content.split('\\n');\n\n for (const secretPattern of SECRET_PATTERNS) {\n // Reset regex lastIndex to avoid issues with global flag\n secretPattern.pattern.lastIndex = 0;\n\n let match;\n while ((match = secretPattern.pattern.exec(content)) !== null) {\n const matchIndex = match.index;\n\n // Skip if in a comment\n if (isInComment(content, matchIndex)) {\n continue;\n }\n\n // Get the actual secret value (either from capture group or full match)\n const secretValue =\n secretPattern.matchGroup !== undefined ? match[secretPattern.matchGroup] : match[0];\n\n // Skip if no secret value found\n if (!secretValue) {\n continue;\n }\n\n // Skip short values for generic patterns\n if (secretPattern.name === 'generic-secret' && secretValue.length < MIN_SECRET_LENGTH) {\n continue;\n }\n\n // Skip placeholder values\n if (isPlaceholder(secretValue)) {\n continue;\n }\n\n // Skip known false-positive values\n if (isFalsePositiveValue(secretValue)) {\n continue;\n }\n\n // For generic-secret, require minimum entropy to filter out\n // natural language config values like tokenType = \"keyword\"\n if (secretPattern.name === 'generic-secret') {\n const entropy = calculateSecretEntropy(secretValue);\n if (entropy < MIN_GENERIC_SECRET_ENTROPY) {\n continue;\n }\n }\n\n const lineNumber = getLineNumber(content, matchIndex);\n const lineContent = lines[lineNumber - 1]?.trim() || '';\n\n evidences.push({\n filePath,\n lineNumber,\n lineContent: lineContent.length > 100 ? lineContent.slice(0, 100) + '...' : lineContent,\n matchedPattern: secretPattern.name,\n snippet: `Detected ${secretPattern.name}: ${secretValue.slice(0, 20)}${secretValue.length > 20 ? '...' : ''}`,\n });\n }\n }\n }\n\n return evidences;\n },\n};\n","import type { DetectionRule } from '../rule.interface.js';\nimport type { Evidence } from '../../types/index.js';\nimport type { ExtensionManifest } from '../../types/index.js';\n\nexport const medExcessiveActivation: DetectionRule = {\n id: 'EG-MED-001',\n name: 'Excessive Activation Events',\n description:\n 'Extension uses \"*\" activation event which means it activates on every action, potentially for surveillance',\n severity: 'medium',\n category: 'excessive-permission',\n enabled: true,\n\n detect(_files: Map<string, string>, manifest: ExtensionManifest): Evidence[] {\n const evidences: Evidence[] = [];\n\n const activationEvents = manifest.activationEvents ?? [];\n\n // Check for \"*\" activation event\n if (activationEvents.includes('*')) {\n evidences.push({\n filePath: 'package.json',\n lineNumber: 1,\n matchedPattern: 'activation-star',\n snippet: 'activationEvents: [\"*\"]',\n lineContent: 'Extension activates on every VS Code action',\n });\n }\n\n // Check for onStartupFinished (runs immediately after VS Code starts)\n if (activationEvents.includes('onStartupFinished')) {\n evidences.push({\n filePath: 'package.json',\n lineNumber: 1,\n matchedPattern: 'activation-startup',\n snippet: 'activationEvents: [\"onStartupFinished\"]',\n lineContent: 'Extension activates immediately on VS Code startup',\n });\n }\n\n return evidences;\n },\n};\n","import { ruleRegistry } from '../rule-registry.js';\nimport { critDataExfiltration } from './crit-data-exfiltration.js';\nimport { critRemoteExecution } from './crit-remote-execution.js';\nimport { critCredentialAccess } from './crit-credential-access.js';\nimport { highSuspiciousNetwork } from './high-suspicious-network.js';\nimport { highObfuscatedCode } from './high-obfuscated-code.js';\nimport { highHardcodedSecret } from './high-hardcoded-secret.js';\nimport { medExcessiveActivation } from './med-excessive-activation.js';\n\nexport function registerBuiltInRules(): void {\n ruleRegistry.register(critDataExfiltration);\n ruleRegistry.register(critRemoteExecution);\n ruleRegistry.register(critCredentialAccess);\n ruleRegistry.register(highSuspiciousNetwork);\n ruleRegistry.register(highObfuscatedCode);\n ruleRegistry.register(highHardcodedSecret);\n ruleRegistry.register(medExcessiveActivation);\n}\n\nexport {\n critDataExfiltration,\n critRemoteExecution,\n critCredentialAccess,\n highSuspiciousNetwork,\n highObfuscatedCode,\n highHardcodedSecret,\n medExcessiveActivation,\n};\n\n/**\n * All built-in detection rules with their metadata.\n * Useful for CLI commands that list rules.\n */\nexport const DETECTION_RULES = [\n critDataExfiltration,\n critRemoteExecution,\n critCredentialAccess,\n highSuspiciousNetwork,\n highObfuscatedCode,\n highHardcodedSecret,\n medExcessiveActivation,\n];\n","import type { ExtensionManifest } from '../types/index.js';\n\n/**\n * Inferred extension category used to adjust finding severity.\n * Extensions in different categories have different \"normal\" behaviors.\n */\nexport type ExtensionCategory =\n | 'theme' // Color themes, icon themes — should have zero runtime behavior\n | 'language' // Grammars, syntax highlighting, snippets — minimal runtime\n | 'ai-assistant' // AI coding tools — legitimately need network, process, env\n | 'scm' // Source control — may access git-credentials legitimately\n | 'debugger' // Debuggers — may spawn processes legitimately\n | 'linter' // Linters, formatters — may spawn processes\n | 'language-support' // Language servers, Python, Go, Rust — spawn interpreters/compilers\n | 'developer-tools' // Code runners, REST clients, live servers — spawn processes, network\n | 'remote-development' // Remote-SSH, Dev Containers, WSL — spawn processes, network\n | 'testing' // Test runners — spawn test processes\n | 'notebook' // Jupyter, notebooks — spawn kernels, network\n | 'general'; // Everything else\n\n/**\n * Publishers known to provide language support extensions (Python, Go, Rust, etc.)\n * These extensions legitimately spawn language servers and interpreters.\n */\nconst LANGUAGE_SUPPORT_PUBLISHERS = [\n 'ms-python',\n 'ms-vscode',\n 'golang',\n 'rust-lang',\n 'microsoft',\n 'redhat',\n 'oracle',\n 'julialang',\n 'haskell',\n // Additional language support publishers\n 'zigtools',\n 'elixir-lsp',\n 'dart-code',\n 'scala-lang',\n 'vscjava',\n 'crystal-lang-tools',\n 'nim-lang',\n 'vlang-vscode',\n];\n\n/**\n * Keywords to detect developer tool extensions (code runners, REST clients, live servers)\n * These extensions legitimately spawn processes and make network requests.\n */\nconst DEVELOPER_TOOL_KEYWORDS = [\n // Code execution\n 'code runner',\n 'coderunner',\n 'run code',\n 'execute code',\n 'run script',\n 'script runner',\n // REST/API clients\n 'rest client',\n 'api client',\n 'http client',\n 'thunder client',\n 'postman',\n 'insomnia',\n 'api tester',\n 'http request',\n // Live servers\n 'live server',\n 'liveserver',\n 'live preview',\n 'browser sync',\n 'browsersync',\n 'local server',\n 'dev server',\n 'http server',\n // Terminal/Shell\n 'terminal',\n 'shell',\n 'integrated terminal',\n // Task runners\n 'task runner',\n 'npm scripts',\n 'gulp',\n 'grunt',\n // Database clients\n 'database client',\n 'sql client',\n 'mongodb client',\n 'redis client',\n];\n\n/**\n * Publishers known to provide developer tools (code runners, REST clients, etc.)\n */\nconst DEVELOPER_TOOL_PUBLISHERS = [\n 'formulahendry', // Code Runner\n 'rangav', // Thunder Client\n 'humao', // REST Client\n 'ritwickdey', // Live Server\n 'techer', // Live Server (alternative)\n 'negokaz', // Live Server (alternative)\n 'qwtel', // HTTP/S Server\n 'hediet', // Debug Visualizer\n 'mtxr', // SQLTools\n 'cweijan', // Database Client\n];\n\n/**\n * Keywords to detect remote development extensions (SSH, containers, WSL)\n * These extensions legitimately spawn processes and make network connections.\n */\nconst REMOTE_DEV_KEYWORDS = [\n 'remote-ssh',\n 'remote ssh',\n 'remote - ssh',\n 'dev container',\n 'devcontainer',\n 'dev-container',\n 'docker container',\n 'wsl',\n 'windows subsystem',\n 'remote development',\n 'remote explorer',\n 'ssh remote',\n 'ssh connection',\n 'container development',\n 'codespace',\n 'github codespaces',\n 'tunnel',\n 'remote tunnels',\n];\n\n/**\n * Publishers known to provide remote development extensions.\n */\nconst REMOTE_DEV_PUBLISHERS = [\n 'ms-vscode-remote', // Remote-SSH, Dev Containers, WSL\n 'ms-azuretools', // Azure (containers, etc.)\n];\n\n/**\n * Keywords to detect testing extensions (test runners, test frameworks)\n * These extensions legitimately spawn test processes.\n */\nconst TESTING_KEYWORDS = [\n 'test runner',\n 'test explorer',\n 'test adapter',\n 'jest runner',\n 'mocha test',\n 'pytest',\n 'vitest',\n 'karma',\n 'jasmine',\n 'cypress',\n 'playwright',\n 'selenium',\n 'unit test',\n 'integration test',\n 'e2e test',\n 'end-to-end test',\n 'test coverage',\n 'code coverage',\n];\n\n/**\n * Publishers known to provide testing extensions.\n */\nconst TESTING_PUBLISHERS = [\n 'hbenl', // Test Explorer UI\n 'firsttris', // Jest Runner\n 'orta', // Jest (vscode-jest)\n 'ms-playwright', // Playwright\n];\n\n/**\n * Keywords to detect notebook extensions (Jupyter, etc.)\n * These extensions legitimately spawn kernels and make network requests.\n */\nconst NOTEBOOK_KEYWORDS = [\n 'jupyter',\n 'notebook',\n 'ipynb',\n 'kernel',\n 'jupyter notebook',\n 'jupyter lab',\n 'ipython',\n 'data science',\n 'interactive python',\n];\n\n/**\n * Publishers known to provide notebook extensions.\n */\nconst NOTEBOOK_PUBLISHERS = [\n 'ms-toolsai', // Jupyter\n];\n\nconst AI_KEYWORDS = [\n 'copilot',\n 'ai',\n 'gpt',\n 'llm',\n 'chatbot',\n 'assistant',\n 'autocomplete',\n 'code completion',\n 'machine learning',\n 'neural',\n 'openai',\n 'anthropic',\n 'gemini',\n 'claude',\n 'codeium',\n 'tabnine',\n 'kilo',\n 'continue',\n 'cursor',\n 'supermaven',\n // Additional AI tools\n 'aider',\n 'codestral',\n 'mistral',\n 'deepseek',\n 'qwen',\n 'sourcery',\n 'codewhisperer',\n 'amazon q',\n 'bito',\n 'blackbox',\n 'codegpt',\n 'cody', // Sourcegraph\n];\n\n/**\n * Infer an extension's category from its manifest (package.json).\n * Uses categories, contributes, keywords, displayName, and description.\n */\nexport function categorizeExtension(manifest: ExtensionManifest): ExtensionCategory {\n const categories = (manifest.categories ?? []).map((c) => c.toLowerCase());\n const contributes = manifest.contributes ?? {};\n const contributeKeys = Object.keys(contributes);\n const keywords = ((manifest as Record<string, unknown>).keywords as string[] | undefined) ?? [];\n const displayName = (manifest.displayName ?? '').toLowerCase();\n const description = (manifest.description ?? '').toLowerCase();\n const name = (manifest.name ?? '').toLowerCase();\n\n // Theme: explicit category or only contributes themes\n if (\n categories.includes('themes') ||\n categories.includes('icon themes') ||\n isThemeOnlyExtension(contributeKeys, contributes)\n ) {\n return 'theme';\n }\n\n // Language/Grammar: contributes grammars or languages with minimal other functionality\n if (isLanguageExtension(contributeKeys, contributes)) {\n return 'language';\n }\n\n // Remote development: SSH, containers, WSL\n // Must be checked BEFORE language-support (ms-vscode-remote contains ms-vscode)\n if (isRemoteDevelopment(manifest, displayName, description, name)) {\n return 'remote-development';\n }\n\n // AI assistant: check categories, keywords, name, description\n if (isAIAssistant(categories, keywords, displayName, description, name)) {\n return 'ai-assistant';\n }\n\n // Language support: extensions that run language servers, interpreters, compilers\n // Must be checked AFTER ai-assistant (some AI tools also have language support)\n if (isLanguageSupport(manifest, categories)) {\n return 'language-support';\n }\n\n // SCM\n if (categories.includes('scm providers') || contributeKeys.includes('scm')) {\n return 'scm';\n }\n\n // Debugger\n if (categories.includes('debuggers') || contributeKeys.includes('debuggers')) {\n return 'debugger';\n }\n\n // Linter / Formatter\n if (\n categories.includes('linters') ||\n categories.includes('formatters') ||\n displayName.includes('lint') ||\n displayName.includes('format') ||\n displayName.includes('prettier') ||\n displayName.includes('eslint')\n ) {\n return 'linter';\n }\n\n // Developer tools: code runners, REST clients, live servers\n if (isDeveloperTool(manifest, displayName, description, name)) {\n return 'developer-tools';\n }\n\n // Testing: test runners, test frameworks\n if (isTesting(manifest, categories, displayName, description, name)) {\n return 'testing';\n }\n\n // Notebook: Jupyter, ipynb\n if (isNotebook(manifest, categories, displayName, description, name, contributeKeys)) {\n return 'notebook';\n }\n\n return 'general';\n}\n\nfunction isThemeOnlyExtension(\n contributeKeys: string[],\n _contributes: Record<string, unknown>\n): boolean {\n const hasThemes = contributeKeys.includes('themes') || contributeKeys.includes('iconThemes');\n if (!hasThemes) return false;\n\n // If the extension ONLY contributes themes (no commands, no other functionality)\n const functionalKeys = contributeKeys.filter(\n (k) => k !== 'themes' && k !== 'iconThemes' && k !== 'colors'\n );\n return functionalKeys.length === 0;\n}\n\nfunction isLanguageExtension(\n contributeKeys: string[],\n contributes: Record<string, unknown>\n): boolean {\n const hasGrammars = contributeKeys.includes('grammars') || contributeKeys.includes('languages');\n if (!hasGrammars) return false;\n\n // Language extension if it contributes grammars/languages but not many commands\n const commands = contributes.commands;\n if (Array.isArray(commands) && commands.length > 3) {\n return false; // Too many commands — likely a full-featured extension\n }\n\n return true;\n}\n\nfunction isAIAssistant(\n categories: string[],\n keywords: string[],\n displayName: string,\n description: string,\n name: string\n): boolean {\n // Check explicit ML category\n if (categories.includes('machine learning') || categories.includes('data science')) {\n return true;\n }\n\n // Check keywords, displayName, description, name against AI keywords\n const searchableText = [\n ...keywords.map((k) => k.toLowerCase()),\n displayName,\n description,\n name,\n ].join(' ');\n\n // Use word boundary matching to avoid false positives like \"continue\" matching \"container\"\n return AI_KEYWORDS.some((kw) => {\n // For multi-word keywords, use simple includes\n if (kw.includes(' ')) {\n return searchableText.includes(kw);\n }\n // For single-word keywords, use word boundary regex\n const regex = new RegExp(`\\\\b${kw}\\\\b`, 'i');\n return regex.test(searchableText);\n });\n}\n\n/**\n * Detect language support extensions (Python, Go, Rust, Java, C++, etc.)\n * These extensions need to spawn language servers and interpreters.\n */\nfunction isLanguageSupport(manifest: ExtensionManifest, categories: string[]): boolean {\n const publisher = (manifest.publisher ?? '').toLowerCase();\n\n // Check known language support publishers\n if (LANGUAGE_SUPPORT_PUBLISHERS.some((p) => publisher.includes(p))) {\n return true;\n }\n\n // Check for \"Programming Languages\" category\n if (categories.includes('programming languages')) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Detect developer tool extensions (code runners, REST clients, live servers, etc.)\n * These extensions legitimately spawn processes and make network requests.\n */\nfunction isDeveloperTool(\n manifest: ExtensionManifest,\n displayName: string,\n description: string,\n name: string\n): boolean {\n const publisher = (manifest.publisher ?? '').toLowerCase();\n\n // Check known developer tool publishers\n if (DEVELOPER_TOOL_PUBLISHERS.some((p) => publisher === p)) {\n return true;\n }\n\n // Check displayName, description, name against developer tool keywords\n const searchableText = [displayName, description, name].join(' ');\n\n return DEVELOPER_TOOL_KEYWORDS.some((kw) => searchableText.includes(kw));\n}\n\n/**\n * Detect remote development extensions (SSH, containers, WSL, etc.)\n * These extensions legitimately spawn processes and make network connections.\n */\nfunction isRemoteDevelopment(\n manifest: ExtensionManifest,\n displayName: string,\n description: string,\n name: string\n): boolean {\n const publisher = (manifest.publisher ?? '').toLowerCase();\n\n // Check known remote development publishers\n if (REMOTE_DEV_PUBLISHERS.some((p) => publisher === p)) {\n return true;\n }\n\n // Check displayName, description, name against remote development keywords\n const searchableText = [displayName, description, name].join(' ');\n\n return REMOTE_DEV_KEYWORDS.some((kw) => searchableText.includes(kw));\n}\n\n/**\n * Detect testing extensions (test runners, test frameworks, etc.)\n * These extensions legitimately spawn test processes.\n */\nfunction isTesting(\n manifest: ExtensionManifest,\n categories: string[],\n displayName: string,\n description: string,\n name: string\n): boolean {\n const publisher = (manifest.publisher ?? '').toLowerCase();\n\n // Check known testing publishers\n if (TESTING_PUBLISHERS.some((p) => publisher === p)) {\n return true;\n }\n\n // Check for \"Testing\" category\n if (categories.includes('testing')) {\n return true;\n }\n\n // Check displayName, description, name against testing keywords\n const searchableText = [displayName, description, name].join(' ');\n\n return TESTING_KEYWORDS.some((kw) => searchableText.includes(kw));\n}\n\n/**\n * Detect notebook extensions (Jupyter, etc.)\n * These extensions legitimately spawn kernels and make network requests.\n */\nfunction isNotebook(\n manifest: ExtensionManifest,\n categories: string[],\n displayName: string,\n description: string,\n name: string,\n contributeKeys: string[]\n): boolean {\n const publisher = (manifest.publisher ?? '').toLowerCase();\n\n // Check known notebook publishers\n if (NOTEBOOK_PUBLISHERS.some((p) => publisher === p)) {\n return true;\n }\n\n // Check for \"Notebooks\" category\n if (categories.includes('notebooks')) {\n return true;\n }\n\n // Check if contributes notebooks\n if (contributeKeys.includes('notebooks') || contributeKeys.includes('notebookRenderer')) {\n return true;\n }\n\n // Check displayName, description, name against notebook keywords\n const searchableText = [displayName, description, name].join(' ');\n\n return NOTEBOOK_KEYWORDS.some((kw) => searchableText.includes(kw));\n}\n","/**\n * Extension Integrity Verifier\n *\n * Verifies that installed extensions match their known-good hashes.\n * This detects supply chain attacks where an official extension has been\n * tampered with after installation or during distribution.\n *\n * Verification methods:\n * 1. File content hash - SHA256 of all JS files concatenated\n * 2. Manifest hash - SHA256 of package.json\n * 3. Structure hash - Hash of file list (detects added/removed files)\n */\n\nimport { createHash } from 'node:crypto';\n\n/**\n * Hash record for a specific extension version\n */\nexport interface ExtensionHash {\n /** Extension ID (publisher.name) */\n extensionId: string;\n /** Version string */\n version: string;\n /** SHA256 of package.json content */\n manifestHash: string;\n /** SHA256 of all JS file contents concatenated (sorted by path) */\n contentHash: string;\n /** SHA256 of sorted file path list */\n structureHash: string;\n /** Combined hash for quick comparison */\n combinedHash: string;\n /** When this hash was recorded */\n recordedAt: string;\n /** Source of the hash (marketplace, manual, etc.) */\n source: 'marketplace' | 'manual' | 'community';\n}\n\n/**\n * Result of integrity verification\n */\nexport interface IntegrityResult {\n extensionId: string;\n version: string;\n status: 'verified' | 'modified' | 'unknown' | 'error';\n /** Which parts were modified (if status is 'modified') */\n modifications?: {\n manifest: boolean;\n content: boolean;\n structure: boolean;\n };\n /** The computed hashes */\n computedHashes?: {\n manifestHash: string;\n contentHash: string;\n structureHash: string;\n combinedHash: string;\n };\n /** The expected hashes (if known) */\n expectedHashes?: ExtensionHash;\n /** Error message if status is 'error' */\n error?: string;\n}\n\n/**\n * Compute SHA256 hash of a string\n */\nexport function sha256(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n}\n\n/**\n * Compute hashes for an extension from its files\n */\nexport function computeExtensionHashes(\n extensionId: string,\n version: string,\n files: Map<string, string>\n): Omit<ExtensionHash, 'recordedAt' | 'source'> {\n // Manifest hash\n const manifestContent = files.get('package.json') ?? '';\n const manifestHash = sha256(manifestContent);\n\n // Content hash - concatenate all JS files sorted by path\n const jsFiles = Array.from(files.entries())\n .filter(([path]) => path.endsWith('.js') || path.endsWith('.ts'))\n .sort(([a], [b]) => a.localeCompare(b));\n\n const contentHash = sha256(jsFiles.map(([, content]) => content).join('\\n'));\n\n // Structure hash - sorted list of all file paths\n const sortedPaths = Array.from(files.keys()).sort();\n const structureHash = sha256(sortedPaths.join('\\n'));\n\n // Combined hash\n const combinedHash = sha256(`${manifestHash}:${contentHash}:${structureHash}`);\n\n return {\n extensionId,\n version,\n manifestHash,\n contentHash,\n structureHash,\n combinedHash,\n };\n}\n\n/**\n * Verify extension integrity against known hashes\n */\nexport function verifyIntegrity(\n extensionId: string,\n version: string,\n files: Map<string, string>,\n knownHashes: Map<string, ExtensionHash>\n): IntegrityResult {\n try {\n // Compute current hashes\n const computed = computeExtensionHashes(extensionId, version, files);\n\n // Look up known hash\n const key = `${extensionId}@${version}`;\n const expected = knownHashes.get(key);\n\n if (!expected) {\n return {\n extensionId,\n version,\n status: 'unknown',\n computedHashes: {\n ...computed,\n },\n };\n }\n\n // Compare hashes\n const manifestModified = computed.manifestHash !== expected.manifestHash;\n const contentModified = computed.contentHash !== expected.contentHash;\n const structureModified = computed.structureHash !== expected.structureHash;\n\n if (manifestModified || contentModified || structureModified) {\n return {\n extensionId,\n version,\n status: 'modified',\n modifications: {\n manifest: manifestModified,\n content: contentModified,\n structure: structureModified,\n },\n computedHashes: {\n ...computed,\n },\n expectedHashes: expected,\n };\n }\n\n return {\n extensionId,\n version,\n status: 'verified',\n computedHashes: {\n ...computed,\n },\n expectedHashes: expected,\n };\n } catch (error) {\n return {\n extensionId,\n version,\n status: 'error',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Create a hash record for an extension (for adding to the database)\n */\nexport function createHashRecord(\n extensionId: string,\n version: string,\n files: Map<string, string>,\n source: ExtensionHash['source'] = 'manual'\n): ExtensionHash {\n const hashes = computeExtensionHashes(extensionId, version, files);\n return {\n ...hashes,\n recordedAt: new Date().toISOString(),\n source,\n };\n}\n","/**\n * Known-Good Hash Database\n *\n * This module manages the database of known-good extension hashes.\n * The database can be:\n * 1. Bundled with the package (for critical extensions)\n * 2. Downloaded from a remote server (for community-maintained hashes)\n * 3. Locally maintained by the user\n *\n * IMPORTANT: This is a static snapshot. For production use, consider:\n * - Fetching from VS Code Marketplace API\n * - Community-maintained hash repository\n * - User-generated baseline from clean install\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ExtensionHash } from './integrity-verifier.js';\n\n/**\n * Hash database structure\n */\nexport interface HashDatabase {\n version: string;\n updatedAt: string;\n hashes: ExtensionHash[];\n}\n\n/**\n * In-memory cache of loaded hashes\n */\nlet hashCache: Map<string, ExtensionHash> | null = null;\n\n/**\n * Default path for local hash database\n */\nexport function getDefaultDatabasePath(): string {\n const homeDir = process.env.HOME || process.env.USERPROFILE || '';\n return path.join(homeDir, '.extension-guard', 'hash-database.json');\n}\n\n/**\n * Load hash database from a JSON file\n */\nexport function loadHashDatabase(filePath?: string): Map<string, ExtensionHash> {\n const dbPath = filePath || getDefaultDatabasePath();\n\n if (hashCache && !filePath) {\n return hashCache;\n }\n\n const hashes = new Map<string, ExtensionHash>();\n\n try {\n if (fs.existsSync(dbPath)) {\n const content = fs.readFileSync(dbPath, 'utf8');\n const db: HashDatabase = JSON.parse(content);\n\n for (const hash of db.hashes) {\n const key = `${hash.extensionId}@${hash.version}`;\n hashes.set(key, hash);\n }\n }\n } catch {\n // Silently fail - database might not exist yet\n }\n\n // Also load bundled hashes\n const bundled = getBundledHashes();\n for (const [key, hash] of bundled) {\n if (!hashes.has(key)) {\n hashes.set(key, hash);\n }\n }\n\n if (!filePath) {\n hashCache = hashes;\n }\n\n return hashes;\n}\n\n/**\n * Save hash database to a JSON file\n */\nexport function saveHashDatabase(hashes: Map<string, ExtensionHash>, filePath?: string): void {\n const dbPath = filePath || getDefaultDatabasePath();\n const dir = path.dirname(dbPath);\n\n // Ensure directory exists\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n const db: HashDatabase = {\n version: '1.0',\n updatedAt: new Date().toISOString(),\n hashes: Array.from(hashes.values()),\n };\n\n fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));\n\n // Update cache\n if (!filePath) {\n hashCache = hashes;\n }\n}\n\n/**\n * Add or update a hash in the database\n */\nexport function addHash(hash: ExtensionHash, filePath?: string): void {\n const hashes = loadHashDatabase(filePath);\n const key = `${hash.extensionId}@${hash.version}`;\n hashes.set(key, hash);\n saveHashDatabase(hashes, filePath);\n}\n\n/**\n * Get a hash from the database\n */\nexport function getHash(\n extensionId: string,\n version: string,\n filePath?: string\n): ExtensionHash | undefined {\n const hashes = loadHashDatabase(filePath);\n return hashes.get(`${extensionId}@${version}`);\n}\n\n/**\n * Clear the hash cache (useful for testing)\n */\nexport function clearHashCache(): void {\n hashCache = null;\n}\n\n/**\n * Bundled hashes for critical extensions\n *\n * These are hashes of known-good versions of high-risk extensions.\n * They are bundled with the package to provide baseline protection\n * without requiring network access.\n *\n * NOTE: In production, these should be regularly updated and\n * ideally fetched from a trusted source.\n */\nfunction getBundledHashes(): Map<string, ExtensionHash> {\n const hashes = new Map<string, ExtensionHash>();\n\n // This is a placeholder structure.\n // In production, this would contain actual verified hashes.\n //\n // Example:\n // {\n // extensionId: 'github.copilot',\n // version: '1.388.0',\n // manifestHash: 'abc123...',\n // contentHash: 'def456...',\n // structureHash: 'ghi789...',\n // combinedHash: 'jkl012...',\n // recordedAt: '2026-02-01T00:00:00Z',\n // source: 'marketplace',\n // }\n\n return hashes;\n}\n\n/**\n * Generate a baseline database from currently installed extensions\n * This is useful for users to create their own trusted baseline\n */\nexport async function generateBaseline(\n _extensionPaths: string[],\n _outputPath?: string\n): Promise<{ generated: number; errors: string[] }> {\n // This is implemented in CLI directly for better UX\n // Keeping this function signature for API completeness\n return {\n generated: 0,\n errors: ['Use CLI baseline command instead'],\n };\n}\n","/**\n * Bundle/Minified File Detector\n *\n * Detects if a JavaScript file is bundled/minified output from tools like:\n * - webpack\n * - esbuild\n * - rollup\n * - parcel\n * - vite\n *\n * Bundled files often trigger false positives because:\n * - They contain many library dependencies inlined\n * - Minification creates high-entropy code patterns\n * - Source maps and comments are stripped\n */\n\nexport interface BundleDetectionResult {\n isBundled: boolean;\n confidence: 'high' | 'medium' | 'low';\n reasons: string[];\n bundler?: string;\n}\n\n/**\n * Common bundler signatures in the output\n */\nconst BUNDLER_SIGNATURES: Record<string, RegExp[]> = {\n webpack: [\n /\\/\\*{3}\\/ var __webpack_/,\n /\\/\\*! For license information /,\n /webpackChunk/,\n /__webpack_require__/,\n /\\/\\*\\*\\*\\/ \\(/,\n ],\n esbuild: [\n /\\/\\/ src\\//,\n /__esm\\s*\\(/,\n /__export\\s*\\(/,\n /var __defProp\\s*=/,\n /var __getOwnPropDesc\\s*=/,\n ],\n rollup: [\n /\\/\\*\\* @license/,\n /\\(function \\(global, factory\\)/,\n /typeof exports === 'object'/,\n /define\\(\\['exports'/,\n ],\n parcel: [/parcelRequire/, /@parcel\\/transformer/],\n vite: [/vite\\/modulepreload-polyfill/, /import\\.meta\\.hot/],\n browserify: [/require=\\(function e\\(t,n,r\\)/, /typeof require==\"function\"/],\n};\n\n/**\n * Patterns indicating minified code\n * Note: Currently checked via line length heuristics instead\n */\n// const MINIFICATION_PATTERNS = [\n// /[,;]\\s*[a-z]\\s*=/gi,\n// /\\)\\s*\\{\\s*return\\s+[a-z]\\s*\\(/gi,\n// ];\n\n/**\n * Common chunk patterns\n */\nconst CHUNK_PATTERNS = [\n /\\d+\\.chunk\\.js$/i,\n /chunk-[a-f0-9]+\\.js$/i,\n /\\.bundle\\.js$/i,\n /\\.min\\.js$/i,\n /\\.prod\\.js$/i,\n /vendor[\\.\\-]/i,\n /runtime[\\.\\-][a-f0-9]+\\.js$/i,\n];\n\n/**\n * Detect if a file is a bundled/minified output\n */\nexport function detectBundle(filePath: string, content: string): BundleDetectionResult {\n const reasons: string[] = [];\n let detectedBundler: string | undefined;\n\n // Check filename patterns\n const filename = filePath.split('/').pop() || filePath;\n for (const pattern of CHUNK_PATTERNS) {\n if (pattern.test(filename)) {\n reasons.push(`Filename matches chunk pattern: ${filename}`);\n break;\n }\n }\n\n // Check for bundler signatures\n for (const [bundler, patterns] of Object.entries(BUNDLER_SIGNATURES)) {\n for (const pattern of patterns) {\n if (pattern.test(content)) {\n reasons.push(`Contains ${bundler} signature`);\n detectedBundler = bundler;\n break;\n }\n }\n if (detectedBundler) break;\n }\n\n // Check for minification indicators\n const lines = content.split('\\n');\n const longLineCount = lines.filter((line) => line.length > 500).length;\n const totalLines = lines.length;\n\n if (totalLines > 0 && longLineCount / totalLines > 0.1) {\n reasons.push(`High percentage of long lines (${longLineCount}/${totalLines})`);\n }\n\n // Check for average line length (minified files have very long average)\n const totalChars = content.length;\n const avgLineLength = totalChars / Math.max(totalLines, 1);\n if (avgLineLength > 200) {\n reasons.push(`High average line length (${Math.round(avgLineLength)} chars)`);\n }\n\n // Check for source map reference\n if (/\\/\\/# sourceMappingURL=/.test(content)) {\n reasons.push('Contains source map reference');\n }\n\n // Check for common bundled patterns\n if (/\\(self\\[\"webpackChunk/.test(content)) {\n reasons.push('Contains webpack chunk pattern');\n if (!detectedBundler) detectedBundler = 'webpack';\n }\n\n // Check for many export/import patterns (common in bundled code)\n const exportCount = (content.match(/export\\s*\\{|exports\\./g) || []).length;\n if (exportCount > 20) {\n reasons.push(`Many export statements (${exportCount})`);\n }\n\n // Determine confidence level\n let confidence: 'high' | 'medium' | 'low' = 'low';\n if (detectedBundler || reasons.length >= 3) {\n confidence = 'high';\n } else if (reasons.length >= 2) {\n confidence = 'medium';\n }\n\n return {\n isBundled: reasons.length > 0,\n confidence,\n reasons,\n bundler: detectedBundler,\n };\n}\n\n/**\n * Check if a file path looks like a bundled output location\n */\nexport function isBundleOutputPath(filePath: string): boolean {\n const bundleOutputDirs = [\n '/dist/',\n '/build/',\n '/out/',\n '/lib/',\n '/.output/',\n '/bundle/',\n '/packed/',\n '/compiled/',\n ];\n\n const normalizedPath = filePath.toLowerCase();\n return bundleOutputDirs.some((dir) => normalizedPath.includes(dir));\n}\n\n/**\n * Determine if findings from this file should be treated with reduced severity\n * because it's likely bundled code (which commonly contains many false positives)\n */\nexport function shouldReduceSeverityForBundle(\n filePath: string,\n content: string\n): { reduce: boolean; reason?: string } {\n // First check if it's in a typical bundle output directory\n if (isBundleOutputPath(filePath)) {\n const result = detectBundle(filePath, content);\n if (result.isBundled && result.confidence !== 'low') {\n return {\n reduce: true,\n reason: `Bundled file (${result.bundler || 'detected'}, ${result.confidence} confidence)`,\n };\n }\n }\n\n // Also check files that end with common bundle extensions\n if (/\\.(bundle|min|prod|chunk)\\.js$/i.test(filePath)) {\n return {\n reduce: true,\n reason: 'Bundle filename pattern',\n };\n }\n\n return { reduce: false };\n}\n","import type { Reporter, ReporterOptions } from './reporter.interface.js';\nimport type { FullScanReport, ScanResult, Severity } from '../types/index.js';\n\nconst SEVERITY_ORDER: Record<Severity, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n info: 4,\n};\n\nexport class JsonReporter implements Reporter {\n readonly format = 'json';\n\n generate(report: FullScanReport, options: ReporterOptions = {}): string {\n const { includeEvidence = true, includeSafe = true, minSeverity = 'info' } = options;\n\n const filteredResults = this.filterResults(report.results, {\n includeSafe,\n minSeverity,\n includeEvidence,\n });\n\n const output = {\n ...report,\n results: filteredResults,\n };\n\n return JSON.stringify(output, null, 2);\n }\n\n private filterResults(\n results: ScanResult[],\n options: { includeSafe: boolean; minSeverity: Severity; includeEvidence: boolean }\n ): ScanResult[] {\n let filtered = results;\n\n if (!options.includeSafe) {\n filtered = filtered.filter((r) => r.riskLevel !== 'safe' && r.riskLevel !== 'low');\n }\n\n const minOrder = SEVERITY_ORDER[options.minSeverity];\n\n return filtered.map((result) => {\n const filteredFindings = result.findings.filter(\n (f) => SEVERITY_ORDER[f.severity] <= minOrder\n );\n\n const findingsOutput = options.includeEvidence\n ? filteredFindings\n : filteredFindings.map(({ evidence, ...rest }) => rest);\n\n return {\n ...result,\n findings: findingsOutput as ScanResult['findings'],\n };\n });\n }\n}\n","import type { Reporter, ReporterOptions } from './reporter.interface.js';\nimport type { FullScanReport } from '../types/index.js';\n\ninterface SarifRule {\n id: string;\n name: string;\n shortDescription: { text: string };\n fullDescription: { text: string };\n defaultConfiguration: { level: 'error' | 'warning' | 'note' };\n properties?: { 'security-severity'?: string; tags?: string[] };\n}\n\ninterface SarifResult {\n ruleId: string;\n ruleIndex: number;\n level: 'error' | 'warning' | 'note';\n message: { text: string };\n locations: Array<{\n physicalLocation: {\n artifactLocation: { uri: string };\n region?: { startLine: number; startColumn?: number };\n };\n }>;\n properties?: Record<string, unknown>;\n}\n\ninterface SarifOutput {\n $schema: string;\n version: string;\n runs: Array<{\n tool: {\n driver: {\n name: string;\n version: string;\n informationUri: string;\n rules: SarifRule[];\n };\n };\n results: SarifResult[];\n }>;\n}\n\nconst SEVERITY_TO_LEVEL: Record<string, 'error' | 'warning' | 'note'> = {\n critical: 'error',\n high: 'error',\n medium: 'warning',\n low: 'note',\n info: 'note',\n};\n\nconst SEVERITY_TO_SCORE: Record<string, string> = {\n critical: '9.0',\n high: '7.0',\n medium: '5.0',\n low: '3.0',\n info: '1.0',\n};\n\nexport class SarifReporter implements Reporter {\n readonly format = 'sarif';\n\n generate(report: FullScanReport, _options?: ReporterOptions): string {\n const rules = this.extractRules(report);\n const results = this.extractResults(report, rules);\n\n const sarif: SarifOutput = {\n $schema:\n 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',\n version: '2.1.0',\n runs: [\n {\n tool: {\n driver: {\n name: 'Extension Guard',\n version: report.version,\n informationUri: 'https://github.com/aspect-guard/extension-guard',\n rules,\n },\n },\n results,\n },\n ],\n };\n\n return JSON.stringify(sarif, null, 2);\n }\n\n private extractRules(report: FullScanReport): SarifRule[] {\n const ruleMap = new Map<string, SarifRule>();\n\n for (const result of report.results) {\n for (const finding of result.findings) {\n if (!ruleMap.has(finding.ruleId)) {\n ruleMap.set(finding.ruleId, {\n id: finding.ruleId,\n name: finding.title,\n shortDescription: { text: finding.title },\n fullDescription: { text: finding.description },\n defaultConfiguration: { level: SEVERITY_TO_LEVEL[finding.severity] || 'note' },\n properties: {\n 'security-severity': SEVERITY_TO_SCORE[finding.severity] || '1.0',\n tags: ['security', finding.category],\n },\n });\n }\n }\n }\n\n return Array.from(ruleMap.values());\n }\n\n private extractResults(report: FullScanReport, rules: SarifRule[]): SarifResult[] {\n const results: SarifResult[] = [];\n const ruleIndexMap = new Map(rules.map((r, i) => [r.id, i]));\n\n for (const scanResult of report.results) {\n for (const finding of scanResult.findings) {\n const ruleIndex = ruleIndexMap.get(finding.ruleId) ?? 0;\n\n results.push({\n ruleId: finding.ruleId,\n ruleIndex,\n level: SEVERITY_TO_LEVEL[finding.severity] || 'note',\n message: {\n text: `${finding.title} in ${scanResult.extensionId}: ${finding.description}`,\n },\n locations: [\n {\n physicalLocation: {\n artifactLocation: {\n uri: `${scanResult.extensionId}/${finding.evidence.filePath}`,\n },\n region: finding.evidence.lineNumber\n ? {\n startLine: finding.evidence.lineNumber,\n startColumn: finding.evidence.columnNumber,\n }\n : undefined,\n },\n },\n ],\n properties: {\n extensionId: scanResult.extensionId,\n trustScore: scanResult.trustScore,\n mitreAttackId: finding.mitreAttackId,\n },\n });\n }\n }\n\n return results;\n }\n}\n","import type { Reporter, ReporterOptions } from './reporter.interface.js';\nimport type { FullScanReport, ScanResult, Finding, Severity } from '../types/index.js';\n\nconst SEVERITY_EMOJI: Record<Severity, string> = {\n critical: '🔴',\n high: '🟠',\n medium: '🟡',\n low: '🟢',\n info: '⚪',\n};\n\nconst RISK_EMOJI: Record<string, string> = {\n critical: '⛔',\n high: '🔴',\n medium: '🟡',\n low: '🟢',\n safe: '✅',\n};\n\nexport class MarkdownReporter implements Reporter {\n readonly format = 'markdown';\n\n generate(report: FullScanReport, options: ReporterOptions = {}): string {\n const { includeSafe = false } = options;\n const lines: string[] = [];\n\n lines.push('# Extension Guard Scan Report');\n lines.push('');\n lines.push(`**Scan ID:** \\`${report.scanId}\\``);\n lines.push(`**Date:** ${new Date(report.timestamp).toLocaleString()}`);\n lines.push(`**Extension Guard Version:** ${report.version}`);\n lines.push('');\n\n // Environment\n lines.push('## Environment');\n lines.push('');\n lines.push(`- **OS:** ${report.environment.os}`);\n for (const ide of report.environment.ides) {\n lines.push(`- **${ide.name}:** ${ide.path} (${ide.extensionCount} extensions)`);\n }\n lines.push('');\n\n // Summary\n lines.push('## Summary');\n lines.push('');\n lines.push(`| Metric | Value |`);\n lines.push(`|--------|-------|`);\n lines.push(`| Total Extensions | ${report.totalExtensions} |`);\n lines.push(`| Unique Extensions | ${report.uniqueExtensions} |`);\n lines.push(`| Health Score | ${report.summary.overallHealthScore}% |`);\n lines.push(`| Scan Duration | ${(report.scanDurationMs / 1000).toFixed(2)}s |`);\n lines.push('');\n\n // Risk Level Breakdown\n lines.push('### Risk Level Distribution');\n lines.push('');\n lines.push('| Risk Level | Count |');\n lines.push('|------------|-------|');\n for (const [level, count] of Object.entries(report.summary.byRiskLevel)) {\n if (count > 0 || includeSafe) {\n lines.push(`| ${RISK_EMOJI[level] || ''} ${level} | ${count} |`);\n }\n }\n lines.push('');\n\n // Severity Breakdown\n const totalFindings = Object.values(report.summary.bySeverity).reduce((a, b) => a + b, 0);\n if (totalFindings > 0) {\n lines.push('### Findings by Severity');\n lines.push('');\n lines.push('| Severity | Count |');\n lines.push('|----------|-------|');\n for (const [severity, count] of Object.entries(report.summary.bySeverity)) {\n if (count > 0) {\n lines.push(`| ${SEVERITY_EMOJI[severity as Severity] || ''} ${severity} | ${count} |`);\n }\n }\n lines.push('');\n }\n\n // Critical and High Risk Extensions\n const riskyResults = report.results.filter(\n (r) => r.riskLevel === 'critical' || r.riskLevel === 'high'\n );\n\n if (riskyResults.length > 0) {\n lines.push('## ⚠️ High Risk Extensions');\n lines.push('');\n for (const result of riskyResults) {\n lines.push(...this.formatExtensionResult(result));\n }\n }\n\n // Medium Risk Extensions\n const mediumResults = report.results.filter((r) => r.riskLevel === 'medium');\n if (mediumResults.length > 0) {\n lines.push('## Medium Risk Extensions');\n lines.push('');\n for (const result of mediumResults) {\n lines.push(...this.formatExtensionResult(result));\n }\n }\n\n // Safe Extensions (if requested)\n if (includeSafe) {\n const safeResults = report.results.filter(\n (r) => r.riskLevel === 'safe' || r.riskLevel === 'low'\n );\n if (safeResults.length > 0) {\n lines.push('## ✅ Safe Extensions');\n lines.push('');\n lines.push('| Extension | Version | Trust Score |');\n lines.push('|-----------|---------|-------------|');\n for (const result of safeResults) {\n lines.push(`| ${result.extensionId} | ${result.version} | ${result.trustScore}/100 |`);\n }\n lines.push('');\n }\n }\n\n // Footer\n lines.push('---');\n lines.push('');\n lines.push('*Generated by [Extension Guard](https://github.com/aspect-guard/extension-guard)*');\n\n return lines.join('\\n');\n }\n\n private formatExtensionResult(result: ScanResult): string[] {\n const lines: string[] = [];\n\n lines.push(`### ${RISK_EMOJI[result.riskLevel] || ''} ${result.extensionId}`);\n lines.push('');\n lines.push(`- **Display Name:** ${result.displayName}`);\n lines.push(`- **Version:** ${result.version}`);\n lines.push(`- **Publisher:** ${result.metadata.publisher.name}`);\n lines.push(`- **Trust Score:** ${result.trustScore}/100`);\n lines.push(`- **Risk Level:** ${result.riskLevel}`);\n lines.push('');\n\n if (result.findings.length > 0) {\n lines.push('#### Findings');\n lines.push('');\n for (const finding of result.findings) {\n lines.push(...this.formatFinding(finding));\n }\n }\n\n return lines;\n }\n\n private formatFinding(finding: Finding): string[] {\n const lines: string[] = [];\n const emoji = SEVERITY_EMOJI[finding.severity] || '';\n\n lines.push(`- ${emoji} **${finding.severity.toUpperCase()}:** ${finding.title}`);\n lines.push(` - ${finding.description}`);\n if (finding.evidence.filePath) {\n const location = finding.evidence.lineNumber\n ? `${finding.evidence.filePath}:${finding.evidence.lineNumber}`\n : finding.evidence.filePath;\n lines.push(` - 📍 Location: \\`${location}\\``);\n }\n if (finding.mitreAttackId) {\n lines.push(` - 🎯 MITRE ATT&CK: ${finding.mitreAttackId}`);\n }\n lines.push('');\n\n return lines;\n }\n}\n","/**\n * Policy Loader\n *\n * Loads and validates Extension Guard policy configuration files.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { PolicyConfig } from './policy.types.js';\n\nconst DEFAULT_CONFIG_NAME = '.extension-guard.json';\n\n/**\n * Load and validate a policy configuration file.\n *\n * @param configPath - Optional path to the config file. If not provided,\n * searches for .extension-guard.json in the current directory.\n * @returns The parsed PolicyConfig or null if not found.\n * @throws Error if the file exists but is invalid JSON or fails validation.\n */\nexport async function loadPolicyConfig(configPath?: string): Promise<PolicyConfig | null> {\n const resolvedPath = configPath ?? path.join(process.cwd(), DEFAULT_CONFIG_NAME);\n\n try {\n const content = await fs.readFile(resolvedPath, 'utf-8');\n const config = JSON.parse(content) as unknown;\n\n validatePolicyConfig(config);\n\n return config as PolicyConfig;\n } catch (error) {\n if (isNodeError(error) && error.code === 'ENOENT') {\n return null;\n }\n throw error;\n }\n}\n\n/**\n * Validate that the parsed config matches the expected PolicyConfig schema.\n *\n * @param config - The parsed JSON object\n * @throws Error if validation fails\n */\nfunction validatePolicyConfig(config: unknown): asserts config is PolicyConfig {\n if (typeof config !== 'object' || config === null) {\n throw new Error('Policy config must be an object');\n }\n\n const obj = config as Record<string, unknown>;\n\n // Version is required\n if (typeof obj.version !== 'string') {\n throw new Error('Policy config must have a \"version\" field of type string');\n }\n\n // Validate scanning section if present\n if (obj.scanning !== undefined) {\n validateScanningConfig(obj.scanning);\n }\n\n // Validate policy section if present\n if (obj.policy !== undefined) {\n validatePolicySection(obj.policy);\n }\n}\n\n/**\n * Validate the scanning configuration section.\n */\nfunction validateScanningConfig(scanning: unknown): void {\n if (typeof scanning !== 'object' || scanning === null) {\n throw new Error('scanning must be an object');\n }\n\n const obj = scanning as Record<string, unknown>;\n\n if (obj.minSeverity !== undefined) {\n const validSeverities = ['critical', 'high', 'medium', 'low', 'info'];\n if (!validSeverities.includes(obj.minSeverity as string)) {\n throw new Error(`scanning.minSeverity must be one of: ${validSeverities.join(', ')}`);\n }\n }\n\n if (obj.skipRules !== undefined) {\n if (!Array.isArray(obj.skipRules) || !obj.skipRules.every((r) => typeof r === 'string')) {\n throw new Error('scanning.skipRules must be an array of strings');\n }\n }\n\n if (obj.timeout !== undefined) {\n if (typeof obj.timeout !== 'number' || obj.timeout <= 0) {\n throw new Error('scanning.timeout must be a positive number');\n }\n }\n}\n\n/**\n * Validate the policy configuration section.\n */\nfunction validatePolicySection(policy: unknown): void {\n if (typeof policy !== 'object' || policy === null) {\n throw new Error('policy must be an object');\n }\n\n const obj = policy as Record<string, unknown>;\n\n if (obj.allowlist !== undefined) {\n if (!Array.isArray(obj.allowlist) || !obj.allowlist.every((id) => typeof id === 'string')) {\n throw new Error('policy.allowlist must be an array of extension ID strings');\n }\n }\n\n if (obj.blocklist !== undefined) {\n if (!Array.isArray(obj.blocklist) || !obj.blocklist.every((id) => typeof id === 'string')) {\n throw new Error('policy.blocklist must be an array of extension ID strings');\n }\n }\n\n if (obj.rules !== undefined) {\n validatePolicyRules(obj.rules);\n }\n}\n\n/**\n * Validate the policy rules section.\n */\nfunction validatePolicyRules(rules: unknown): void {\n if (typeof rules !== 'object' || rules === null) {\n throw new Error('policy.rules must be an object');\n }\n\n const obj = rules as Record<string, unknown>;\n const validActions = ['block', 'warn', 'info'];\n\n if (obj.minTrustScore !== undefined) {\n const rule = obj.minTrustScore as Record<string, unknown>;\n if (typeof rule.threshold !== 'number' || rule.threshold < 0 || rule.threshold > 100) {\n throw new Error('minTrustScore.threshold must be a number between 0 and 100');\n }\n if (!validActions.includes(rule.action as string)) {\n throw new Error(`minTrustScore.action must be one of: ${validActions.join(', ')}`);\n }\n }\n\n if (obj.requireVerifiedPublisher !== undefined) {\n const rule = obj.requireVerifiedPublisher as Record<string, unknown>;\n if (typeof rule.enabled !== 'boolean') {\n throw new Error('requireVerifiedPublisher.enabled must be a boolean');\n }\n if (!validActions.includes(rule.action as string)) {\n throw new Error(`requireVerifiedPublisher.action must be one of: ${validActions.join(', ')}`);\n }\n if (rule.exceptions !== undefined) {\n if (!Array.isArray(rule.exceptions) || !rule.exceptions.every((e) => typeof e === 'string')) {\n throw new Error('requireVerifiedPublisher.exceptions must be an array of strings');\n }\n }\n }\n\n if (obj.maxDaysSinceUpdate !== undefined) {\n const rule = obj.maxDaysSinceUpdate as Record<string, unknown>;\n if (typeof rule.days !== 'number' || rule.days <= 0) {\n throw new Error('maxDaysSinceUpdate.days must be a positive number');\n }\n if (!validActions.includes(rule.action as string)) {\n throw new Error(`maxDaysSinceUpdate.action must be one of: ${validActions.join(', ')}`);\n }\n }\n\n if (obj.blockObfuscated !== undefined) {\n const rule = obj.blockObfuscated as Record<string, unknown>;\n if (typeof rule.enabled !== 'boolean') {\n throw new Error('blockObfuscated.enabled must be a boolean');\n }\n if (!validActions.includes(rule.action as string)) {\n throw new Error(`blockObfuscated.action must be one of: ${validActions.join(', ')}`);\n }\n }\n}\n\n/**\n * Type guard for Node.js errors with error codes.\n */\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && 'code' in error;\n}\n","/**\n * Policy Engine\n *\n * Evaluates extension scan results against policy rules to determine compliance.\n */\n\nimport type { PolicyConfig, PolicyViolation } from './policy.types.js';\nimport type { ScanResult } from '../types/index.js';\n\n/**\n * Rule ID for obfuscated code detection.\n * Must match the rule ID in high-obfuscated-code.ts\n */\nconst OBFUSCATION_RULE_ID = 'EG-HIGH-001';\n\n/**\n * Milliseconds in a day for date calculations.\n */\nconst MS_PER_DAY = 1000 * 60 * 60 * 24;\n\n/**\n * Extended metadata interface that may include lastUpdated.\n * The base ExtensionInfo type doesn't include this, but it may be\n * added by the scanner when available from marketplace data.\n */\ninterface ExtendedMetadata {\n lastUpdated?: string;\n publisher: { verified: boolean; name: string };\n}\n\n/**\n * PolicyEngine evaluates scan results against configured policy rules.\n *\n * @example\n * ```typescript\n * const config = await loadPolicyConfig();\n * const engine = new PolicyEngine(config);\n * const violations = engine.evaluate(scanResults);\n *\n * if (engine.hasBlockingViolations()) {\n * console.error('Policy check failed');\n * process.exit(1);\n * }\n * ```\n */\nexport class PolicyEngine {\n private violations: PolicyViolation[] = [];\n\n /**\n * Create a new PolicyEngine instance.\n *\n * @param config - The policy configuration to evaluate against\n */\n constructor(private config: PolicyConfig) {}\n\n /**\n * Evaluate scan results against the configured policy.\n *\n * Checks are applied in this order for each extension:\n * 1. Blocklist - if matched, block immediately and skip other checks\n * 2. Allowlist - if matched, skip all other checks\n * 3. Individual rules (minTrustScore, blockObfuscated, etc.)\n *\n * @param results - Array of scan results to evaluate\n * @returns Array of policy violations found\n */\n evaluate(results: ScanResult[]): PolicyViolation[] {\n this.violations = [];\n\n for (const result of results) {\n const extId = result.extensionId;\n\n // Check blocklist first\n if (this.config.policy?.blocklist?.includes(extId)) {\n this.violations.push({\n extensionId: extId,\n rule: 'blocklist',\n message: 'Extension is blocklisted',\n action: 'block',\n });\n continue; // Skip all other checks for blocklisted extensions\n }\n\n // Check allowlist - skip all other checks if allowed\n if (this.config.policy?.allowlist?.includes(extId)) {\n continue;\n }\n\n // Check individual rules\n this.checkMinTrustScore(result);\n this.checkBlockObfuscated(result);\n this.checkRequireVerifiedPublisher(result);\n this.checkMaxDaysSinceUpdate(result);\n }\n\n return this.violations;\n }\n\n /**\n * Check if there are any violations with 'block' action.\n *\n * @returns true if any blocking violations exist\n */\n hasBlockingViolations(): boolean {\n return this.violations.some((v) => v.action === 'block');\n }\n\n /**\n * Get all violations from the last evaluation.\n *\n * @returns Array of all policy violations\n */\n getViolations(): PolicyViolation[] {\n return this.violations;\n }\n\n /**\n * Check minTrustScore rule.\n */\n private checkMinTrustScore(result: ScanResult): void {\n const rule = this.config.policy?.rules?.minTrustScore;\n if (!rule) return;\n\n if (result.trustScore < rule.threshold) {\n this.violations.push({\n extensionId: result.extensionId,\n rule: 'minTrustScore',\n message: `Trust score ${result.trustScore} below threshold ${rule.threshold}`,\n action: rule.action,\n });\n }\n }\n\n /**\n * Check blockObfuscated rule.\n */\n private checkBlockObfuscated(result: ScanResult): void {\n const rule = this.config.policy?.rules?.blockObfuscated;\n if (!rule?.enabled) return;\n\n const hasObfuscation = result.findings.some((f) => f.ruleId === OBFUSCATION_RULE_ID);\n if (hasObfuscation) {\n this.violations.push({\n extensionId: result.extensionId,\n rule: 'blockObfuscated',\n message: 'Extension contains obfuscated code',\n action: rule.action,\n });\n }\n }\n\n /**\n * Check requireVerifiedPublisher rule.\n */\n private checkRequireVerifiedPublisher(result: ScanResult): void {\n const rule = this.config.policy?.rules?.requireVerifiedPublisher;\n if (!rule?.enabled) return;\n\n const metadata = result.metadata as ExtendedMetadata;\n if (!metadata.publisher.verified) {\n // Check if this extension is in the exceptions list\n if (rule.exceptions?.includes(result.extensionId)) {\n return;\n }\n\n this.violations.push({\n extensionId: result.extensionId,\n rule: 'requireVerifiedPublisher',\n message: 'Extension publisher is not verified',\n action: rule.action,\n });\n }\n }\n\n /**\n * Check maxDaysSinceUpdate rule.\n */\n private checkMaxDaysSinceUpdate(result: ScanResult): void {\n const rule = this.config.policy?.rules?.maxDaysSinceUpdate;\n if (!rule) return;\n\n const metadata = result.metadata as ExtendedMetadata;\n if (!metadata.lastUpdated) return;\n\n const lastUpdatedDate = new Date(metadata.lastUpdated);\n const daysSinceUpdate = Math.floor((Date.now() - lastUpdatedDate.getTime()) / MS_PER_DAY);\n\n if (daysSinceUpdate > rule.days) {\n this.violations.push({\n extensionId: result.extensionId,\n rule: 'maxDaysSinceUpdate',\n message: `Extension not updated in ${daysSinceUpdate} days (max: ${rule.days})`,\n action: rule.action,\n });\n }\n }\n}\n","// Extension Guard Core - Scanning Engine\n// @aspect-guard/core\n\nexport const VERSION = '0.5.1';\n\n// Types\nexport * from './types/index.js';\n\n// Scanner\nexport { ExtensionGuardScanner } from './scanner/scanner.js';\nexport {\n detectIDEPaths,\n IDE_PATHS,\n expandPath,\n getSupportedIDEs,\n isIDEInstalled,\n getIDEExtensionPath,\n} from './scanner/ide-detector.js';\nexport { readExtension, readExtensionsFromDirectory } from './scanner/extension-reader.js';\nexport { collectFiles, shouldCollectFile } from './scanner/file-collector.js';\nexport { categorizeExtension } from './scanner/extension-categorizer.js';\nexport type { ExtensionCategory } from './scanner/extension-categorizer.js';\n\n// Rules\nexport * from './rules/index.js';\nexport { registerBuiltInRules, DETECTION_RULES } from './rules/built-in/index.js';\nexport { adjustFindings } from './rules/finding-adjuster.js';\nexport type { AdjustFindingsOptions } from './rules/finding-adjuster.js';\n\n// Trusted Publishers\nexport {\n TRUSTED_PUBLISHERS,\n TRUSTED_EXTENSION_IDS,\n isTrustedPublisher,\n isTrustedExtension,\n} from './data/trusted-publishers.js';\n\n// Verified Publishers\nexport { VERIFIED_PUBLISHERS, isVerifiedPublisher } from './data/verified-publishers.js';\n\n// Popular Extensions\nexport {\n ALL_POPULAR_EXTENSIONS,\n MEGA_POPULAR_EXTENSIONS,\n POPULAR_EXTENSIONS,\n getPopularityTier,\n isMegaPopular,\n isPopular,\n} from './data/popular-extensions.js';\nexport type { PopularExtension } from './data/popular-extensions.js';\n\n// Bundle Detection\nexport {\n detectBundle,\n isBundleOutputPath,\n shouldReduceSeverityForBundle,\n} from './analyzers/bundle-detector.js';\nexport type { BundleDetectionResult } from './analyzers/bundle-detector.js';\n\n// Reporter\nexport * from './reporter/index.js';\n\n// Policy\nexport * from './policy/index.js';\n\n// Integrity Verification\nexport * from './integrity/index.js';\n"],"mappings":"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","names":["os","randomUUID","fs","path","stat","fs","path","stat","match","path","fs","path","randomUUID","SEVERITY_ORDER","fs","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspect-guard/core",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Core scanning engine for Extension Guard",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",