@trailofbits/vsix-audit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +281 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +703 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/scanner/batch.d.ts +12 -0
- package/dist/scanner/batch.d.ts.map +1 -0
- package/dist/scanner/batch.js +104 -0
- package/dist/scanner/batch.js.map +1 -0
- package/dist/scanner/bundler.d.ts +35 -0
- package/dist/scanner/bundler.d.ts.map +1 -0
- package/dist/scanner/bundler.js +120 -0
- package/dist/scanner/bundler.js.map +1 -0
- package/dist/scanner/cache.d.ts +45 -0
- package/dist/scanner/cache.d.ts.map +1 -0
- package/dist/scanner/cache.js +153 -0
- package/dist/scanner/cache.js.map +1 -0
- package/dist/scanner/cache.test.d.ts +2 -0
- package/dist/scanner/cache.test.d.ts.map +1 -0
- package/dist/scanner/cache.test.js +149 -0
- package/dist/scanner/cache.test.js.map +1 -0
- package/dist/scanner/capabilities.d.ts +29 -0
- package/dist/scanner/capabilities.d.ts.map +1 -0
- package/dist/scanner/capabilities.js +217 -0
- package/dist/scanner/capabilities.js.map +1 -0
- package/dist/scanner/checks/ast.d.ts +3 -0
- package/dist/scanner/checks/ast.d.ts.map +1 -0
- package/dist/scanner/checks/ast.js +469 -0
- package/dist/scanner/checks/ast.js.map +1 -0
- package/dist/scanner/checks/ast.test.d.ts +2 -0
- package/dist/scanner/checks/ast.test.d.ts.map +1 -0
- package/dist/scanner/checks/ast.test.js +389 -0
- package/dist/scanner/checks/ast.test.js.map +1 -0
- package/dist/scanner/checks/behavioral.d.ts +3 -0
- package/dist/scanner/checks/behavioral.d.ts.map +1 -0
- package/dist/scanner/checks/behavioral.js +367 -0
- package/dist/scanner/checks/behavioral.js.map +1 -0
- package/dist/scanner/checks/blocklist.d.ts +3 -0
- package/dist/scanner/checks/blocklist.d.ts.map +1 -0
- package/dist/scanner/checks/blocklist.js +32 -0
- package/dist/scanner/checks/blocklist.js.map +1 -0
- package/dist/scanner/checks/blocklist.test.d.ts +2 -0
- package/dist/scanner/checks/blocklist.test.d.ts.map +1 -0
- package/dist/scanner/checks/blocklist.test.js +74 -0
- package/dist/scanner/checks/blocklist.test.js.map +1 -0
- package/dist/scanner/checks/chains.d.ts +35 -0
- package/dist/scanner/checks/chains.d.ts.map +1 -0
- package/dist/scanner/checks/chains.js +505 -0
- package/dist/scanner/checks/chains.js.map +1 -0
- package/dist/scanner/checks/chains.test.d.ts +2 -0
- package/dist/scanner/checks/chains.test.d.ts.map +1 -0
- package/dist/scanner/checks/chains.test.js +250 -0
- package/dist/scanner/checks/chains.test.js.map +1 -0
- package/dist/scanner/checks/dataflow.d.ts +3 -0
- package/dist/scanner/checks/dataflow.d.ts.map +1 -0
- package/dist/scanner/checks/dataflow.js +316 -0
- package/dist/scanner/checks/dataflow.js.map +1 -0
- package/dist/scanner/checks/dependencies.d.ts +13 -0
- package/dist/scanner/checks/dependencies.d.ts.map +1 -0
- package/dist/scanner/checks/dependencies.js +225 -0
- package/dist/scanner/checks/dependencies.js.map +1 -0
- package/dist/scanner/checks/dependencies.test.d.ts +2 -0
- package/dist/scanner/checks/dependencies.test.d.ts.map +1 -0
- package/dist/scanner/checks/dependencies.test.js +248 -0
- package/dist/scanner/checks/dependencies.test.js.map +1 -0
- package/dist/scanner/checks/finding-quality.test.d.ts +8 -0
- package/dist/scanner/checks/finding-quality.test.d.ts.map +1 -0
- package/dist/scanner/checks/finding-quality.test.js +164 -0
- package/dist/scanner/checks/finding-quality.test.js.map +1 -0
- package/dist/scanner/checks/ioc.d.ts +20 -0
- package/dist/scanner/checks/ioc.d.ts.map +1 -0
- package/dist/scanner/checks/ioc.js +234 -0
- package/dist/scanner/checks/ioc.js.map +1 -0
- package/dist/scanner/checks/ioc.test.d.ts +2 -0
- package/dist/scanner/checks/ioc.test.d.ts.map +1 -0
- package/dist/scanner/checks/ioc.test.js +298 -0
- package/dist/scanner/checks/ioc.test.js.map +1 -0
- package/dist/scanner/checks/manifest.d.ts +6 -0
- package/dist/scanner/checks/manifest.d.ts.map +1 -0
- package/dist/scanner/checks/manifest.js +123 -0
- package/dist/scanner/checks/manifest.js.map +1 -0
- package/dist/scanner/checks/manifest.test.d.ts +2 -0
- package/dist/scanner/checks/manifest.test.d.ts.map +1 -0
- package/dist/scanner/checks/manifest.test.js +108 -0
- package/dist/scanner/checks/manifest.test.js.map +1 -0
- package/dist/scanner/checks/obfuscation.d.ts +3 -0
- package/dist/scanner/checks/obfuscation.d.ts.map +1 -0
- package/dist/scanner/checks/obfuscation.js +432 -0
- package/dist/scanner/checks/obfuscation.js.map +1 -0
- package/dist/scanner/checks/obfuscation.test.d.ts +2 -0
- package/dist/scanner/checks/obfuscation.test.d.ts.map +1 -0
- package/dist/scanner/checks/obfuscation.test.js +399 -0
- package/dist/scanner/checks/obfuscation.test.js.map +1 -0
- package/dist/scanner/checks/package.d.ts +17 -0
- package/dist/scanner/checks/package.d.ts.map +1 -0
- package/dist/scanner/checks/package.js +422 -0
- package/dist/scanner/checks/package.js.map +1 -0
- package/dist/scanner/checks/package.test.d.ts +2 -0
- package/dist/scanner/checks/package.test.d.ts.map +1 -0
- package/dist/scanner/checks/package.test.js +518 -0
- package/dist/scanner/checks/package.test.js.map +1 -0
- package/dist/scanner/checks/patterns.d.ts +5 -0
- package/dist/scanner/checks/patterns.d.ts.map +1 -0
- package/dist/scanner/checks/patterns.js +251 -0
- package/dist/scanner/checks/patterns.js.map +1 -0
- package/dist/scanner/checks/patterns.test.d.ts +2 -0
- package/dist/scanner/checks/patterns.test.d.ts.map +1 -0
- package/dist/scanner/checks/patterns.test.js +147 -0
- package/dist/scanner/checks/patterns.test.js.map +1 -0
- package/dist/scanner/checks/unicode.d.ts +3 -0
- package/dist/scanner/checks/unicode.d.ts.map +1 -0
- package/dist/scanner/checks/unicode.js +247 -0
- package/dist/scanner/checks/unicode.js.map +1 -0
- package/dist/scanner/checks/unicode.test.d.ts +2 -0
- package/dist/scanner/checks/unicode.test.d.ts.map +1 -0
- package/dist/scanner/checks/unicode.test.js +202 -0
- package/dist/scanner/checks/unicode.test.js.map +1 -0
- package/dist/scanner/checks/yara.d.ts +23 -0
- package/dist/scanner/checks/yara.d.ts.map +1 -0
- package/dist/scanner/checks/yara.js +349 -0
- package/dist/scanner/checks/yara.js.map +1 -0
- package/dist/scanner/checks/yara.test.d.ts +2 -0
- package/dist/scanner/checks/yara.test.d.ts.map +1 -0
- package/dist/scanner/checks/yara.test.js +126 -0
- package/dist/scanner/checks/yara.test.js.map +1 -0
- package/dist/scanner/constants.d.ts +18 -0
- package/dist/scanner/constants.d.ts.map +1 -0
- package/dist/scanner/constants.js +37 -0
- package/dist/scanner/constants.js.map +1 -0
- package/dist/scanner/detection-coverage.test.d.ts +2 -0
- package/dist/scanner/detection-coverage.test.d.ts.map +1 -0
- package/dist/scanner/detection-coverage.test.js +216 -0
- package/dist/scanner/detection-coverage.test.js.map +1 -0
- package/dist/scanner/download.d.ts +76 -0
- package/dist/scanner/download.d.ts.map +1 -0
- package/dist/scanner/download.js +339 -0
- package/dist/scanner/download.js.map +1 -0
- package/dist/scanner/download.test.d.ts +2 -0
- package/dist/scanner/download.test.d.ts.map +1 -0
- package/dist/scanner/download.test.js +149 -0
- package/dist/scanner/download.test.js.map +1 -0
- package/dist/scanner/index.d.ts +8 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +167 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/index.test.d.ts +2 -0
- package/dist/scanner/index.test.d.ts.map +1 -0
- package/dist/scanner/index.test.js +71 -0
- package/dist/scanner/index.test.js.map +1 -0
- package/dist/scanner/loaders/zoo.d.ts +3 -0
- package/dist/scanner/loaders/zoo.d.ts.map +1 -0
- package/dist/scanner/loaders/zoo.js +112 -0
- package/dist/scanner/loaders/zoo.js.map +1 -0
- package/dist/scanner/types.d.ts +118 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +2 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/scanner/utils.d.ts +14 -0
- package/dist/scanner/utils.d.ts.map +1 -0
- package/dist/scanner/utils.js +25 -0
- package/dist/scanner/utils.js.map +1 -0
- package/dist/scanner/vsix.d.ts +6 -0
- package/dist/scanner/vsix.d.ts.map +1 -0
- package/dist/scanner/vsix.js +213 -0
- package/dist/scanner/vsix.js.map +1 -0
- package/dist/scanner/vsix.test.d.ts +2 -0
- package/dist/scanner/vsix.test.d.ts.map +1 -0
- package/dist/scanner/vsix.test.js +355 -0
- package/dist/scanner/vsix.test.js.map +1 -0
- package/package.json +60 -0
- package/zoo/blocklist/extensions.json +201 -0
- package/zoo/iocs/blockchain-extensions.txt +21 -0
- package/zoo/iocs/c2-domains.txt +50 -0
- package/zoo/iocs/c2-ips.txt +24 -0
- package/zoo/iocs/hashes.txt +47 -0
- package/zoo/iocs/malicious-npm.txt +85 -0
- package/zoo/iocs/wallets.txt +18 -0
- package/zoo/signatures/yara/README.md +46 -0
- package/zoo/signatures/yara/blockchain_c2.yar +48 -0
- package/zoo/signatures/yara/code_execution.yar +165 -0
- package/zoo/signatures/yara/credential_harvesting.yar +116 -0
- package/zoo/signatures/yara/crypto_wallet_targeting.yar +92 -0
- package/zoo/signatures/yara/data_exfiltration.yar +207 -0
- package/zoo/signatures/yara/google_calendar_c2.yar +187 -0
- package/zoo/signatures/yara/messaging_c2.yar +103 -0
- package/zoo/signatures/yara/multi_stage_attacks.yar +331 -0
- package/zoo/signatures/yara/obfuscation_patterns.yar +208 -0
- package/zoo/signatures/yara/powershell_attacks.yar +116 -0
- package/zoo/signatures/yara/rat_capabilities.yar +243 -0
- package/zoo/signatures/yara/self_propagation.yar +239 -0
- package/zoo/signatures/yara/unicode_stealth.yar +48 -0
- package/zoo/signatures/yara/websocket_c2.yar +83 -0
package/README.md
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# vsix-audit
|
|
2
|
+
|
|
3
|
+
Security scanner for VS Code extensions. Detects malicious extensions before installation by analyzing code patterns, indicators of compromise, and known malware signatures.
|
|
4
|
+
|
|
5
|
+
## The Problem
|
|
6
|
+
|
|
7
|
+
VS Code extensions run with full trust and the same permissions as the editor itself. Malicious extensions have been found in both the official Microsoft marketplace and OpenVSX:
|
|
8
|
+
|
|
9
|
+
- **Credential theft** - SSH keys, browser cookies, password manager databases
|
|
10
|
+
- **Cryptocurrency theft** - Wallet files, clipboard hijacking for addresses
|
|
11
|
+
- **Source code exfiltration** - Stealing proprietary code via Discord webhooks
|
|
12
|
+
- **Cryptominers and RATs** - CoinIMP miners, ScreenConnect RATs, multi-stage loaders
|
|
13
|
+
- **Self-propagation** - GlassWorm spread by modifying installed extensions
|
|
14
|
+
|
|
15
|
+
**Real campaigns we track:** GlassWorm, TigerJack, Evelyn, WhiteCobra, OctoRAT, Shiba, MUT-9332, FAMOUS CHOLLIMA
|
|
16
|
+
|
|
17
|
+
## Detection Modules
|
|
18
|
+
|
|
19
|
+
The scanner runs 5 detection modules against each extension:
|
|
20
|
+
|
|
21
|
+
### Package Analysis (`package.ts`)
|
|
22
|
+
|
|
23
|
+
Examines `package.json` and extension manifest for suspicious configurations.
|
|
24
|
+
|
|
25
|
+
| Check | What It Detects | Severity |
|
|
26
|
+
| ---------------------- | ------------------------------------------------------------------------------- | --------------- |
|
|
27
|
+
| Blocklist | Extension ID matches known malicious extensions | Critical |
|
|
28
|
+
| Wildcard activation | `activationEvents: ["*"]` - runs on every action | High |
|
|
29
|
+
| Startup activation | `onStartupFinished` - runs at VS Code launch | Medium |
|
|
30
|
+
| Theme with code | Theme extension that has a `main` entry point | High |
|
|
31
|
+
| Malicious npm packages | Dependencies matching known malware packages | Critical |
|
|
32
|
+
| Typosquatting | Dependencies within edit distance 1-2 of popular packages (lodash, axios, etc.) | High |
|
|
33
|
+
| Lifecycle scripts | `preinstall`/`postinstall` scripts with suspicious patterns | Critical/Medium |
|
|
34
|
+
|
|
35
|
+
### Indicators of Compromise (`ioc.ts`)
|
|
36
|
+
|
|
37
|
+
Matches against curated threat intelligence from `zoo/iocs/`.
|
|
38
|
+
|
|
39
|
+
| Check | Detection Method | Severity |
|
|
40
|
+
| -------------- | ------------------------------------------------------------------- | -------- |
|
|
41
|
+
| Malware hashes | SHA256 hash of files matches known samples | Critical |
|
|
42
|
+
| C2 domains | Domain extraction matched against blocklist | Critical |
|
|
43
|
+
| C2 IPs | IPv4 extraction (excludes private ranges) matched against blocklist | Critical |
|
|
44
|
+
| Crypto wallets | BTC (legacy/SegWit/Bech32), ETH, Monero, Solana address patterns | High |
|
|
45
|
+
|
|
46
|
+
### AST Analysis (`ast.ts`)
|
|
47
|
+
|
|
48
|
+
OXC-based parsing to detect structural patterns that regex can't catch.
|
|
49
|
+
|
|
50
|
+
| Rule | What It Detects | Severity |
|
|
51
|
+
| -------------------------- | ------------------------------------------------ | -------- |
|
|
52
|
+
| `AST_EVAL_DYNAMIC` | `eval(variable)` - non-literal argument | High |
|
|
53
|
+
| `AST_FUNCTION_CONSTRUCTOR` | `new Function(string)` - runtime code generation | High |
|
|
54
|
+
| `AST_DYNAMIC_REQUIRE` | `require(variable)` - computed module loads | Medium |
|
|
55
|
+
| `AST_DYNAMIC_IMPORT` | `import(variable)` - computed dynamic imports | Medium |
|
|
56
|
+
| `AST_PROCESS_BINDING` | `process.binding()` - Node.js internals access | High |
|
|
57
|
+
| `AST_GLOBAL_THIS_EVAL` | `globalThis.eval` - indirect eval access | High |
|
|
58
|
+
|
|
59
|
+
### Obfuscation Detection (`obfuscation.ts`)
|
|
60
|
+
|
|
61
|
+
Detects obfuscation techniques used to hide malicious intent.
|
|
62
|
+
|
|
63
|
+
| Rule | Detection Method | Severity |
|
|
64
|
+
| -------------------------- | ----------------------------------------------------------------- | -------- |
|
|
65
|
+
| `OBFUSCATION_HIGH_ENTROPY` | Shannon entropy >5.5 bits/char (200-char windows) | Medium |
|
|
66
|
+
| `ZERO_WIDTH_CHARS` | Zero-width spaces/joiners hiding code (U+200B-200D) | High |
|
|
67
|
+
| `VARIATION_SELECTOR` | GlassWorm-style hidden data in variation selectors (U+FE00-FE0F) | Critical |
|
|
68
|
+
| `BIDI_OVERRIDE` | Trojan Source attacks using bidirectional overrides (U+202A-202E) | Critical |
|
|
69
|
+
| `UNICODE_ASCII_ESCAPE` | `\u00XX` escapes for normal ASCII chars (obfuscation) | Medium |
|
|
70
|
+
| `CYRILLIC_HOMOGLYPH` | Cyrillic letters that look like Latin (а/a, е/e, с/c) | High |
|
|
71
|
+
| `OTHER_INVISIBLE_CHARS` | Soft hyphens, combining marks, format controls | Medium |
|
|
72
|
+
| `INVISIBLE_CODE_EXECUTION` | Invisible chars near `eval`/`Function`/`exec` | Critical |
|
|
73
|
+
|
|
74
|
+
JavaScript obfuscation patterns (hex variables, `fromCharCode` arrays, eval+decode, packers) are now detected via YARA rules for better accuracy.
|
|
75
|
+
|
|
76
|
+
### YARA Rules (`yara.ts`)
|
|
77
|
+
|
|
78
|
+
External YARA engine for complex pattern matching. Rules loaded from `zoo/signatures/yara/`. Requires `yara` CLI (`brew install yara`).
|
|
79
|
+
|
|
80
|
+
| Rule File | Detects |
|
|
81
|
+
| ----------------------------- | -------------------------------------------------------------- |
|
|
82
|
+
| `blockchain_c2.yar` | Solana RPC C2, memo parsing, blockchain-based command channels |
|
|
83
|
+
| `code_execution.yar` | `eval`, `Function` constructor, `child_process` patterns |
|
|
84
|
+
| `credential_harvesting.yar` | NPM/GitHub/SSH credential theft, `.npmrc` access |
|
|
85
|
+
| `crypto_wallet_targeting.yar` | MetaMask, Phantom, Exodus wallet extension targeting |
|
|
86
|
+
| `data_exfiltration.yar` | Discord webhooks, SSH key theft, browser data exfil |
|
|
87
|
+
| `google_calendar_c2.yar` | Google Calendar API abuse for C2 communication |
|
|
88
|
+
| `multi_stage_attacks.yar` | Dropper chains, reverse shells, keylogger patterns |
|
|
89
|
+
| `obfuscation_patterns.yar` | Hex variables, `fromCharCode`, packed/encoded code |
|
|
90
|
+
| `powershell_attacks.yar` | Hidden windows, `-ExecutionPolicy Bypass`, AMSI evasion |
|
|
91
|
+
| `rat_capabilities.yar` | SOCKS proxy, VNC, remote command execution |
|
|
92
|
+
| `self_propagation.yar` | GlassWorm-style worm propagation via extension modification |
|
|
93
|
+
| `unicode_stealth.yar` | Invisible Unicode, variation selectors, homoglyphs |
|
|
94
|
+
|
|
95
|
+
### Triage-Friendly Output
|
|
96
|
+
|
|
97
|
+
Every finding includes context to help quickly determine if it's a real threat:
|
|
98
|
+
|
|
99
|
+
- **Legitimate uses** - Why this pattern exists in benign extensions
|
|
100
|
+
- **Red flags** - What makes the same pattern suspicious in context
|
|
101
|
+
- **Severity** - Critical/high/medium/low based on risk and intent signals
|
|
102
|
+
- **Location** - File path and line number for the match
|
|
103
|
+
|
|
104
|
+
The goal is rich context for human/agent review, not just pass/fail.
|
|
105
|
+
|
|
106
|
+
## Installation
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
npm install -g vsix-audit
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Requires Node.js 22 or later.
|
|
113
|
+
|
|
114
|
+
## Usage
|
|
115
|
+
|
|
116
|
+
### Commands
|
|
117
|
+
|
|
118
|
+
**Scan an extension for security issues:**
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
vsix-audit scan ./extension.vsix
|
|
122
|
+
vsix-audit scan publisher.extension-name
|
|
123
|
+
vsix-audit scan openvsx:publisher.extension-name
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Download an extension for offline analysis:**
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
vsix-audit download ms-python.python
|
|
130
|
+
vsix-audit download ms-python.python@2024.1.0 -o ./downloads
|
|
131
|
+
vsix-audit download openvsx:redhat.java
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Show extension metadata:**
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
vsix-audit info ./extension.vsix
|
|
138
|
+
vsix-audit info ./extension-folder
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Displays: name, publisher, version, activation events, entry points, contributions, dependencies, file count, and size.
|
|
142
|
+
|
|
143
|
+
### Registry Prefixes
|
|
144
|
+
|
|
145
|
+
| Prefix | Registry |
|
|
146
|
+
| -------------- | ------------------------------ |
|
|
147
|
+
| (none) | VS Code Marketplace (default) |
|
|
148
|
+
| `marketplace:` | VS Code Marketplace (explicit) |
|
|
149
|
+
| `openvsx:` | Open VSX Registry |
|
|
150
|
+
| `cursor:` | Cursor Extension Marketplace |
|
|
151
|
+
|
|
152
|
+
### Scan Options
|
|
153
|
+
|
|
154
|
+
| Option | Description |
|
|
155
|
+
| ------------------------ | -------------------------------------------------------------------------------- |
|
|
156
|
+
| `-o, --output <format>` | Output format: `text`, `json`, or `sarif` (default: `text`) |
|
|
157
|
+
| `-s, --severity <level>` | Minimum severity to report: `low`, `medium`, `high`, `critical` (default: `low`) |
|
|
158
|
+
| `-r, --recursive` | Recursively scan all .vsix files in a directory |
|
|
159
|
+
| `-j, --jobs <n>` | Number of parallel scans (default: 4, used with --recursive) |
|
|
160
|
+
| `--no-network` | Disable network-based checks |
|
|
161
|
+
| `--no-cache` | Bypass cache, download fresh |
|
|
162
|
+
| `--force` | Re-download even if cached |
|
|
163
|
+
| `--all-registries` | Scan from all registries (Marketplace + OpenVSX + Cursor) |
|
|
164
|
+
|
|
165
|
+
### Extension Cache
|
|
166
|
+
|
|
167
|
+
Downloaded extensions are cached for faster subsequent scans:
|
|
168
|
+
|
|
169
|
+
| Platform | Cache Location |
|
|
170
|
+
| -------- | ------------------------------------------------------- |
|
|
171
|
+
| macOS | `~/Library/Caches/vsix-audit/` |
|
|
172
|
+
| Linux | `$XDG_CACHE_HOME/vsix-audit/` or `~/.cache/vsix-audit/` |
|
|
173
|
+
|
|
174
|
+
Extensions are organized by registry (`marketplace/`, `openvsx/`, `cursor/`).
|
|
175
|
+
|
|
176
|
+
**Cache management commands:**
|
|
177
|
+
|
|
178
|
+
```sh
|
|
179
|
+
vsix-audit cache path # Print cache directory
|
|
180
|
+
vsix-audit cache list [--json] # List cached extensions
|
|
181
|
+
vsix-audit cache clear [pattern] # Clear cache (optional glob pattern)
|
|
182
|
+
vsix-audit cache info <ext-id> # Show cached versions
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Examples:**
|
|
186
|
+
|
|
187
|
+
```sh
|
|
188
|
+
# First scan downloads to cache
|
|
189
|
+
vsix-audit scan ms-python.python
|
|
190
|
+
# → Downloaded ~/.cache/vsix-audit/marketplace/ms-python.python-2024.1.0.vsix
|
|
191
|
+
|
|
192
|
+
# Second scan uses cache
|
|
193
|
+
vsix-audit scan ms-python.python
|
|
194
|
+
# → Using cached ~/.cache/vsix-audit/marketplace/ms-python.python-2024.1.0.vsix
|
|
195
|
+
|
|
196
|
+
# Force re-download
|
|
197
|
+
vsix-audit scan --force ms-python.python
|
|
198
|
+
|
|
199
|
+
# Bypass cache entirely
|
|
200
|
+
vsix-audit scan --no-cache ms-python.python
|
|
201
|
+
|
|
202
|
+
# Clear specific extensions
|
|
203
|
+
vsix-audit cache clear ms-python.*
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Output Formats
|
|
207
|
+
|
|
208
|
+
**Text** (default) - Human-readable report for terminal output.
|
|
209
|
+
|
|
210
|
+
**JSON** - Machine-readable results for integration with other tools.
|
|
211
|
+
|
|
212
|
+
**SARIF** - Static Analysis Results Interchange Format for CI/CD integration.
|
|
213
|
+
|
|
214
|
+
### Exit Codes
|
|
215
|
+
|
|
216
|
+
| Code | Meaning |
|
|
217
|
+
| ---- | ----------------- |
|
|
218
|
+
| 0 | No findings |
|
|
219
|
+
| 1 | Findings detected |
|
|
220
|
+
| 2 | Error during scan |
|
|
221
|
+
|
|
222
|
+
## Threat Intelligence
|
|
223
|
+
|
|
224
|
+
The `zoo/` directory contains threat intelligence for detection:
|
|
225
|
+
|
|
226
|
+
| Directory | Contents |
|
|
227
|
+
| ----------------- | --------------------------------------------------------------------- |
|
|
228
|
+
| `zoo/blocklist/` | Known malicious extension IDs with campaign attribution |
|
|
229
|
+
| `zoo/iocs/` | SHA256 hashes, C2 domains/IPs, crypto wallets, malicious npm packages |
|
|
230
|
+
| `zoo/signatures/` | YARA rules for credential harvesting, RAT behavior, self-propagation |
|
|
231
|
+
|
|
232
|
+
**Campaigns covered:** GlassWorm, Evelyn, TigerJack, OctoRAT, WhiteCobra, Shiba, MUT-9332, FAMOUS CHOLLIMA, ReversingLabs-Dec2025
|
|
233
|
+
|
|
234
|
+
### Malware Samples (for development)
|
|
235
|
+
|
|
236
|
+
Malware samples are in a separate private repository ([trailofbits/vsix-zoo](https://github.com/trailofbits/vsix-zoo)) to avoid Dependabot alerts and AV triggers.
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
# Clone the samples repo (requires access)
|
|
240
|
+
git clone git@github.com:trailofbits/vsix-zoo.git ../vsix-zoo
|
|
241
|
+
|
|
242
|
+
# Run tests with samples
|
|
243
|
+
VSIX_ZOO_PATH=../vsix-zoo/samples npm test
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Development
|
|
247
|
+
|
|
248
|
+
```sh
|
|
249
|
+
git clone https://github.com/trailofbits/vsix-audit.git
|
|
250
|
+
cd vsix-audit
|
|
251
|
+
npm install
|
|
252
|
+
npm run build
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Set up pre-commit hooks:
|
|
256
|
+
|
|
257
|
+
```sh
|
|
258
|
+
prek install
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Run tests:
|
|
262
|
+
|
|
263
|
+
```sh
|
|
264
|
+
npm test
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Type check and lint:
|
|
268
|
+
|
|
269
|
+
```sh
|
|
270
|
+
npm run check
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Run from development directory:
|
|
274
|
+
|
|
275
|
+
```sh
|
|
276
|
+
npm exec -- vsix-audit scan ./extension.vsix
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## License
|
|
280
|
+
|
|
281
|
+
AGPL-3.0
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmEpC,eAAO,MAAM,GAAG,SAGG,CAAC"}
|