vsix-scan
v0.4.0
Published
Deep security analyzer for VSCode extensions
Maintainers
Readme
vsix-scan
Deep security analyzer for Visual Studio Code extensions.
Scans .vsix files and installed extensions for malicious patterns, hardcoded secrets, suspicious network calls, known dependency CVEs, license issues, and marketplace trust signals — from the command line, no VS Code required.
vsix-scan v0.4.0
──────────────────────────────────────────────────
Target: cweijan.vscode-database-client2 (VS Marketplace)
Marketplace: 1,170,145 installs · 4.2★ · published 1935 days ago
Code analysis (AST) (2 findings)
!!! [ast/new-function] new Function(...) constructs code dynamically.
!! [ast/child-process] child_process.exec() call detected.
Dependency vulnerabilities (12 findings)
!! [deps/known-vulnerability] [email protected] — 17 known CVEs
Risk score: 57/100 HIGHWhat it checks
| Analyzer | What it detects |
|---|---|
| Manifest | Wildcard activation (*), postinstall scripts, typosquatting, missing publisher |
| AST (code) | eval(), new Function(), child_process, dynamic require(), obfuscated strings |
| Secrets | AWS/GCP/Azure keys, GitHub tokens, JWTs, high-entropy strings near credential keywords |
| Dependencies | Known CVEs via OSV.dev batch API (npm ecosystem) |
| License | GPL/AGPL (strong copyleft), LGPL/MPL (weak copyleft), unrecognized licenses |
| Webview / CSP | Missing Content-Security-Policy, inline scripts, retainContextWhenHidden |
| Marketplace | Extension age, install count, publisher track record — trust signal findings |
| Custom rules | Your own YAML rules — regex on code or manifest fields |
Installation
npm install -g vsix-scanRequirements: Node.js 18+
Usage
Analyze an extension
# From the VS Marketplace (downloads the latest .vsix automatically)
vsix-scan analyze ms-python.python
# Specific version
vsix-scan analyze [email protected]
# Installed extension folder
vsix-scan analyze esbenp.prettier-vscode-12.4.0
# Local .vsix file
vsix-scan analyze ./my-extension.vsixOutput formats
vsix-scan analyze ms-python.python # terminal (default)
vsix-scan analyze ms-python.python --format json
vsix-scan analyze ms-python.python --format html # saves <id>-report.html
vsix-scan analyze ms-python.python --format sarif > results.sarifExit codes for CI
# Exit 1 if any finding is high or above, exit 2 on tool error
vsix-scan analyze some.extension --fail-on high| Exit code | Meaning |
|---|---|
| 0 | Analysis complete, threshold not exceeded |
| 1 | One or more findings at or above --fail-on severity |
| 2 | Tool error (bad target, network failure, etc.) |
Compare two versions
vsix-scan diff [email protected] [email protected]
vsix-scan diff ./old.vsix ./new.vsix
vsix-scan diff [email protected] [email protected] --format jsonShows fixed findings ✔, new findings ✖, unchanged count, and risk score delta.
Scan all installed extensions
vsix-scan scan-all
vsix-scan scan-all --editor cursor # Cursor, Windsurf, VSCodium also supported
vsix-scan scan-all --format html # saves vsix-scan-all-report.html
vsix-scan scan-all --format json > results.json
vsix-scan scan-all --fail-on criticalWatch mode — auto-scan on install
vsix-scan watch # watches ~/.vscode/extensions
vsix-scan watch --editor cursor
vsix-scan watch --fail-on high # exit 1 if a new extension is riskyDetects newly-installed extensions in real time. Waits 2.5 s for VS Code to finish extracting, then scans and prints a one-liner result. Rings a terminal bell on high/critical findings.
List installed extensions
vsix-scan list
vsix-scan list --editor windsurfCache management
Results are cached for 12 hours under ~/.vsix-scan/cache/. Speeds up repeated
scan-all runs from ~90 s to ~1 s.
vsix-scan cache --stats # show entry count and size
vsix-scan cache --clear # delete all cached resultsUse --no-cache on analyze or scan-all to bypass the cache.
Suppressing findings
Create a .vsix-scan-ignore file in the directory where you run vsix-scan:
# Ignore a specific rule everywhere
deps/known-vulnerability
# Ignore all findings in a file glob
**/vendor/**
dist/generated/*.jsLines containing / are treated as rule IDs; all other lines are file globs
(minimatch syntax).
Custom YAML rules
Create a .yaml file with your own detection rules and pass it with --rules:
rules:
- id: custom/telemetry-url
description: Calls to internal telemetry endpoint
severity: high
target: code
match:
content_regex: 'analytics\.mycompany\.com'
file_glob: "**/*.{js,ts,mjs,cjs}"
message: "Telemetry endpoint call detected."
- id: custom/unpinned-axios
description: axios dependency not pinned to exact version
severity: low
target: manifest
match:
manifest_path: dependencies.axios
manifest_regex: '^\^'
message: "axios is not pinned — use an exact version."vsix-scan analyze some.extension --rules ./my-rules.yamlSee examples/custom-rules.yaml for a complete working example.
Rule fields:
| Field | Values | Description |
|---|---|---|
| id | namespace/name | Unique identifier |
| severity | critical high medium low info | Finding severity |
| target | code manifest any | What to apply the rule to |
| match.content_regex | regex string | Pattern matched against file content |
| match.file_glob | glob pattern | Restrict to matching files (optional) |
| match.manifest_path | dot-path | Key path into package.json, e.g. scripts.postinstall |
| match.manifest_regex | regex string | Pattern matched against the manifest value |
| message | string | Text shown in findings output |
GitHub Action
Add vsix-scan to your CI pipeline to block merges when a vendored extension is risky:
# .github/workflows/security.yml
name: Extension security scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write # required for SARIF upload
steps:
- uses: actions/checkout@v4
- name: Scan extension
id: scan
uses: PabloDomi/[email protected]
with:
target: ms-python.python
format: sarif
fail-on: high
upload-sarif: true
- name: Check risk level
run: |
echo "Risk score: ${{ steps.scan.outputs.risk-score }}"
echo "Risk level: ${{ steps.scan.outputs.risk-level }}"Action inputs:
| Input | Default | Description |
|---|---|---|
| target | (required) | Extension to scan (marketplace ID, .vsix path, or folder) |
| format | sarif | Output format: terminal, json, html, sarif |
| fail-on | high | Minimum severity that causes the action to fail |
| rules | — | Path to an additional YAML rules file |
| upload-sarif | true | Upload SARIF to GitHub Security tab |
Action outputs: risk-score (0–100), risk-level (safe/low/medium/high/critical)
See examples/github-action.yml for a complete copy-pasteable workflow.
Risk scoring
Each finding adds points based on severity. The final score is a weighted combination of code findings and dependency CVEs:
risk_score = min(100, code_score × 0.7 + deps_score × 0.3)| Score | Risk level | |---|---| | 0 | ✅ Safe | | 1–19 | 🔵 Low | | 20–44 | 🟡 Medium | | 45–69 | 🔴 High | | 70–100 | 🚨 Critical |
Dependency CVEs are weighted at 30% to prevent large extensions with many outdated packages from dominating the score when their actual code is clean.
Bundle detection
VS Code extensions commonly ship minified webpack/esbuild bundles. vsix-scan automatically detects bundled files and deduplicates findings from them. A file is considered bundled if:
- It contains webpack/esbuild markers in the first 2 000 bytes, OR
- Any of its first 30 lines is longer than 500 characters
Supported editors
| Editor | Platform | Extension folder |
|---|---|---|
| VS Code | Windows / macOS / Linux | ~/.vscode/extensions |
| Cursor | Windows / macOS / Linux | ~/.cursor/extensions |
| Windsurf | Windows / macOS / Linux | ~/.windsurf/extensions |
| VSCodium | Windows / macOS / Linux | ~/.vscode-oss/extensions |
Use --editor <id> on scan-all, watch, and list.
Development
git clone https://github.com/PabloDomi/vsix-scan
cd vsix-scan
npm install
npm run build
node dist/cli.js analyze esbenp.prettier-vscode-12.4.0Run tests:
npm test
npm run test:coverageLicense
MIT
