@aspect-guard/core 0.1.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -72,6 +72,18 @@ interface Finding {
72
72
  remediation?: string;
73
73
  }
74
74
 
75
+ type IntegrityStatus = 'verified' | 'modified' | 'unknown' | 'skipped' | 'error';
76
+ interface IntegrityInfo {
77
+ status: IntegrityStatus;
78
+ /** Which parts were modified (if status is 'modified') */
79
+ modifications?: {
80
+ manifest: boolean;
81
+ content: boolean;
82
+ structure: boolean;
83
+ };
84
+ /** Combined hash of this extension */
85
+ hash?: string;
86
+ }
75
87
  interface ScanResult {
76
88
  extensionId: string;
77
89
  displayName: string;
@@ -82,6 +94,8 @@ interface ScanResult {
82
94
  metadata: ExtensionInfo;
83
95
  analyzedFiles: number;
84
96
  scanDurationMs: number;
97
+ /** Integrity verification result (only if --verify-integrity is used) */
98
+ integrity?: IntegrityInfo;
85
99
  }
86
100
  interface ScanSummary {
87
101
  byRiskLevel: Record<RiskLevel, number>;
@@ -129,6 +143,10 @@ interface ScanOptions {
129
143
  skipRules?: string[];
130
144
  concurrency?: number;
131
145
  timeout?: number;
146
+ /** Enable integrity verification against known-good hashes */
147
+ verifyIntegrity?: boolean;
148
+ /** Path to custom hash database */
149
+ hashDatabasePath?: string;
132
150
  }
133
151
  interface InspectOptions {
134
152
  vsixPath: string;
@@ -139,6 +157,7 @@ interface InspectOptions {
139
157
  declare class ExtensionGuardScanner {
140
158
  private options;
141
159
  private ruleEngine;
160
+ private hashDatabase;
142
161
  constructor(options?: Partial<ScanOptions>);
143
162
  scan(options?: Partial<ScanOptions>): Promise<FullScanReport>;
144
163
  private scanExtension;
@@ -157,6 +176,17 @@ declare function readExtensionsFromDirectory(directoryPath: string): Promise<Ext
157
176
  declare function shouldCollectFile(filePath: string): boolean;
158
177
  declare function collectFiles(extensionPath: string): Promise<Map<string, string>>;
159
178
 
179
+ /**
180
+ * Inferred extension category used to adjust finding severity.
181
+ * Extensions in different categories have different "normal" behaviors.
182
+ */
183
+ type ExtensionCategory = 'theme' | 'language' | 'ai-assistant' | 'scm' | 'debugger' | 'linter' | 'language-support' | 'developer-tools' | 'remote-development' | 'testing' | 'notebook' | 'general';
184
+ /**
185
+ * Infer an extension's category from its manifest (package.json).
186
+ * Uses categories, contributes, keywords, displayName, and description.
187
+ */
188
+ declare function categorizeExtension(manifest: ExtensionManifest): ExtensionCategory;
189
+
160
190
  interface DetectionRule {
161
191
  id: string;
162
192
  name: string;
@@ -195,6 +225,165 @@ declare const ruleRegistry: RuleRegistry;
195
225
 
196
226
  declare function registerBuiltInRules(): void;
197
227
 
228
+ /**
229
+ * All built-in detection rules with their metadata.
230
+ * Useful for CLI commands that list rules.
231
+ */
232
+ declare const DETECTION_RULES: DetectionRule[];
233
+
234
+ /**
235
+ * Options for adjusting findings.
236
+ */
237
+ interface AdjustFindingsOptions {
238
+ /** Publisher name for soft trust check */
239
+ publisher?: string;
240
+ /** Full extension ID (publisher.name) for soft trust check */
241
+ extensionId?: string;
242
+ /** Skip soft trust adjustments (strict mode) */
243
+ strictMode?: boolean;
244
+ /** Map of file paths to file contents for bundle detection */
245
+ files?: Map<string, string>;
246
+ }
247
+ /**
248
+ * Adjust findings based on the extension's inferred category and trust status.
249
+ *
250
+ * Four layers of adjustment:
251
+ * 1. Category-based: Expected behaviors for extension type (e.g., AI tools use network)
252
+ * 2. Soft Trust: Trusted publishers get an additional severity downgrade
253
+ * 3. Verified Publisher: Verified publishers on marketplace get severity downgrade
254
+ * 4. Popularity: Extensions with 10M+ downloads get double downgrade, 1M+ get single
255
+ *
256
+ * Returns a new array with adjusted findings (original array is not mutated).
257
+ */
258
+ declare function adjustFindings(findings: Finding[], category: ExtensionCategory, options?: AdjustFindingsOptions): Finding[];
259
+
260
+ /**
261
+ * List of well-known, trusted publishers.
262
+ *
263
+ * Extensions from these publishers receive "soft trust" treatment:
264
+ * - Their findings are downgraded one additional severity level
265
+ * - They are NOT completely bypassed (supply chain attacks can hit anyone)
266
+ *
267
+ * This list is intentionally conservative and includes only:
268
+ * - Major IDE vendors (Microsoft, GitHub)
269
+ * - Well-established tool vendors with long track records
270
+ */
271
+ declare const TRUSTED_PUBLISHERS: string[];
272
+ /**
273
+ * Specific extension IDs that are trusted regardless of publisher.
274
+ * Use this for known extensions from smaller publishers.
275
+ */
276
+ declare const TRUSTED_EXTENSION_IDS: string[];
277
+ /**
278
+ * Check if an extension is from a trusted publisher.
279
+ */
280
+ declare function isTrustedPublisher(publisher: string): boolean;
281
+ /**
282
+ * Check if an extension ID is explicitly trusted.
283
+ */
284
+ declare function isTrustedExtension(extensionId: string): boolean;
285
+
286
+ /**
287
+ * List of verified publishers from VS Code Marketplace.
288
+ *
289
+ * These publishers have undergone verification by Microsoft and display
290
+ * a verified badge on the marketplace. Extensions from verified publishers
291
+ * are treated similarly to trusted publishers.
292
+ *
293
+ * Note: This list is maintained manually based on known verified publishers.
294
+ * In the future, this could be fetched from the marketplace API.
295
+ */
296
+ declare const VERIFIED_PUBLISHERS: string[];
297
+ /**
298
+ * Check if a publisher is verified on the marketplace.
299
+ */
300
+ declare function isVerifiedPublisher(publisher: string): boolean;
301
+
302
+ /**
303
+ * List of popular extensions with high download counts.
304
+ *
305
+ * Extensions with millions of downloads have been vetted by the community
306
+ * through widespread usage. Supply chain attacks on these would be extremely
307
+ * visible and risky for attackers.
308
+ *
309
+ * Threshold tiers:
310
+ * - 10M+ downloads: Highest trust (downgrade by 2 severity levels)
311
+ * - 1M+ downloads: High trust (downgrade by 1 severity level)
312
+ *
313
+ * Note: This data is manually maintained. In the future, this could be
314
+ * fetched from the marketplace API and cached locally.
315
+ *
316
+ * Last updated: 2026-02
317
+ */
318
+ interface PopularExtension {
319
+ id: string;
320
+ downloads: number;
321
+ tier: 'mega' | 'popular';
322
+ }
323
+ /**
324
+ * Extensions with 10M+ downloads (mega popular)
325
+ */
326
+ declare const MEGA_POPULAR_EXTENSIONS: PopularExtension[];
327
+ /**
328
+ * Extensions with 1M-10M downloads (popular)
329
+ */
330
+ declare const POPULAR_EXTENSIONS: PopularExtension[];
331
+ /**
332
+ * All popular extensions combined
333
+ */
334
+ declare const ALL_POPULAR_EXTENSIONS: PopularExtension[];
335
+ /**
336
+ * Get popularity tier for an extension.
337
+ * Returns null if not in the popular extensions list.
338
+ */
339
+ declare function getPopularityTier(extensionId: string): 'mega' | 'popular' | null;
340
+ /**
341
+ * Check if an extension is mega popular (10M+ downloads)
342
+ */
343
+ declare function isMegaPopular(extensionId: string): boolean;
344
+ /**
345
+ * Check if an extension is popular (1M+ downloads)
346
+ */
347
+ declare function isPopular(extensionId: string): boolean;
348
+
349
+ /**
350
+ * Bundle/Minified File Detector
351
+ *
352
+ * Detects if a JavaScript file is bundled/minified output from tools like:
353
+ * - webpack
354
+ * - esbuild
355
+ * - rollup
356
+ * - parcel
357
+ * - vite
358
+ *
359
+ * Bundled files often trigger false positives because:
360
+ * - They contain many library dependencies inlined
361
+ * - Minification creates high-entropy code patterns
362
+ * - Source maps and comments are stripped
363
+ */
364
+ interface BundleDetectionResult {
365
+ isBundled: boolean;
366
+ confidence: 'high' | 'medium' | 'low';
367
+ reasons: string[];
368
+ bundler?: string;
369
+ }
370
+ /**
371
+ * Detect if a file is a bundled/minified output
372
+ */
373
+ declare function detectBundle(filePath: string, content: string): BundleDetectionResult;
374
+ /**
375
+ * Check if a file path looks like a bundled output location
376
+ */
377
+ declare function isBundleOutputPath(filePath: string): boolean;
378
+ /**
379
+ * Determine if findings from this file should be treated with reduced severity
380
+ * because it's likely bundled code (which commonly contains many false positives)
381
+ */
382
+ declare function shouldReduceSeverityForBundle(filePath: string, content: string): {
383
+ reduce: boolean;
384
+ reason?: string;
385
+ };
386
+
198
387
  interface ReporterOptions {
199
388
  includeEvidence?: boolean;
200
389
  includeSafe?: boolean;
@@ -390,6 +579,137 @@ declare class PolicyEngine {
390
579
  private checkMaxDaysSinceUpdate;
391
580
  }
392
581
 
393
- declare const VERSION = "0.1.0";
582
+ /**
583
+ * Extension Integrity Verifier
584
+ *
585
+ * Verifies that installed extensions match their known-good hashes.
586
+ * This detects supply chain attacks where an official extension has been
587
+ * tampered with after installation or during distribution.
588
+ *
589
+ * Verification methods:
590
+ * 1. File content hash - SHA256 of all JS files concatenated
591
+ * 2. Manifest hash - SHA256 of package.json
592
+ * 3. Structure hash - Hash of file list (detects added/removed files)
593
+ */
594
+ /**
595
+ * Hash record for a specific extension version
596
+ */
597
+ interface ExtensionHash {
598
+ /** Extension ID (publisher.name) */
599
+ extensionId: string;
600
+ /** Version string */
601
+ version: string;
602
+ /** SHA256 of package.json content */
603
+ manifestHash: string;
604
+ /** SHA256 of all JS file contents concatenated (sorted by path) */
605
+ contentHash: string;
606
+ /** SHA256 of sorted file path list */
607
+ structureHash: string;
608
+ /** Combined hash for quick comparison */
609
+ combinedHash: string;
610
+ /** When this hash was recorded */
611
+ recordedAt: string;
612
+ /** Source of the hash (marketplace, manual, etc.) */
613
+ source: 'marketplace' | 'manual' | 'community';
614
+ }
615
+ /**
616
+ * Result of integrity verification
617
+ */
618
+ interface IntegrityResult {
619
+ extensionId: string;
620
+ version: string;
621
+ status: 'verified' | 'modified' | 'unknown' | 'error';
622
+ /** Which parts were modified (if status is 'modified') */
623
+ modifications?: {
624
+ manifest: boolean;
625
+ content: boolean;
626
+ structure: boolean;
627
+ };
628
+ /** The computed hashes */
629
+ computedHashes?: {
630
+ manifestHash: string;
631
+ contentHash: string;
632
+ structureHash: string;
633
+ combinedHash: string;
634
+ };
635
+ /** The expected hashes (if known) */
636
+ expectedHashes?: ExtensionHash;
637
+ /** Error message if status is 'error' */
638
+ error?: string;
639
+ }
640
+ /**
641
+ * Compute SHA256 hash of a string
642
+ */
643
+ declare function sha256(content: string): string;
644
+ /**
645
+ * Compute hashes for an extension from its files
646
+ */
647
+ declare function computeExtensionHashes(extensionId: string, version: string, files: Map<string, string>): Omit<ExtensionHash, 'recordedAt' | 'source'>;
648
+ /**
649
+ * Verify extension integrity against known hashes
650
+ */
651
+ declare function verifyIntegrity(extensionId: string, version: string, files: Map<string, string>, knownHashes: Map<string, ExtensionHash>): IntegrityResult;
652
+ /**
653
+ * Create a hash record for an extension (for adding to the database)
654
+ */
655
+ declare function createHashRecord(extensionId: string, version: string, files: Map<string, string>, source?: ExtensionHash['source']): ExtensionHash;
656
+
657
+ /**
658
+ * Known-Good Hash Database
659
+ *
660
+ * This module manages the database of known-good extension hashes.
661
+ * The database can be:
662
+ * 1. Bundled with the package (for critical extensions)
663
+ * 2. Downloaded from a remote server (for community-maintained hashes)
664
+ * 3. Locally maintained by the user
665
+ *
666
+ * IMPORTANT: This is a static snapshot. For production use, consider:
667
+ * - Fetching from VS Code Marketplace API
668
+ * - Community-maintained hash repository
669
+ * - User-generated baseline from clean install
670
+ */
671
+
672
+ /**
673
+ * Hash database structure
674
+ */
675
+ interface HashDatabase {
676
+ version: string;
677
+ updatedAt: string;
678
+ hashes: ExtensionHash[];
679
+ }
680
+ /**
681
+ * Default path for local hash database
682
+ */
683
+ declare function getDefaultDatabasePath(): string;
684
+ /**
685
+ * Load hash database from a JSON file
686
+ */
687
+ declare function loadHashDatabase(filePath?: string): Map<string, ExtensionHash>;
688
+ /**
689
+ * Save hash database to a JSON file
690
+ */
691
+ declare function saveHashDatabase(hashes: Map<string, ExtensionHash>, filePath?: string): void;
692
+ /**
693
+ * Add or update a hash in the database
694
+ */
695
+ declare function addHash(hash: ExtensionHash, filePath?: string): void;
696
+ /**
697
+ * Get a hash from the database
698
+ */
699
+ declare function getHash(extensionId: string, version: string, filePath?: string): ExtensionHash | undefined;
700
+ /**
701
+ * Clear the hash cache (useful for testing)
702
+ */
703
+ declare function clearHashCache(): void;
704
+ /**
705
+ * Generate a baseline database from currently installed extensions
706
+ * This is useful for users to create their own trusted baseline
707
+ */
708
+ declare function generateBaseline(_extensionPaths: string[], _outputPath?: string): Promise<{
709
+ generated: number;
710
+ errors: string[];
711
+ }>;
712
+
713
+ declare const VERSION = "0.4.0";
394
714
 
395
- export { type AuditReport, type DetectedIDE, type DetectionRule, type Evidence, ExtensionGuardScanner, type ExtensionInfo, type ExtensionManifest, type Finding, type FindingCategory, type FullScanReport, IDE_PATHS, type InspectOptions, JsonReporter, MarkdownReporter, type PolicyAction, type PolicyConfig, PolicyEngine, type PolicyRules, type PolicyViolation, type Reporter, type ReporterOptions, type RiskLevel, RuleEngine, type RuleEngineOptions, SEVERITY_ORDER, SarifReporter, type ScanOptions, type ScanResult, type ScanSummary, type Severity, VERSION, collectFiles, compareSeverity, detectIDEPaths, expandPath, isAtLeastSeverity, loadPolicyConfig, readExtension, readExtensionsFromDirectory, registerBuiltInRules, ruleRegistry, shouldCollectFile };
715
+ 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, getPopularityTier, isAtLeastSeverity, isBundleOutputPath, isMegaPopular, isPopular, isTrustedExtension, isTrustedPublisher, isVerifiedPublisher, loadHashDatabase, loadPolicyConfig, readExtension, readExtensionsFromDirectory, registerBuiltInRules, ruleRegistry, saveHashDatabase, sha256, shouldCollectFile, shouldReduceSeverityForBundle, verifyIntegrity };