feat(llm-security): add /security ide-scan — VS Code / JetBrains extension prescan (v6.3.0)
New standalone scanner (prefix IDE) discovers installed VS Code extensions across forks (Cursor, Windsurf, VSCodium, code-server, Insiders, Remote-SSH) and runs 7 IDE-specific threat checks: blocklist match (CRITICAL), theme-with-code, sideload (unsigned .vsix), dangerous uninstall hook (HIGH), wildcard activation, extension-pack expansion, typosquat (MEDIUM). Per-extension reuse of UNI/ENT/NET/TNT/MEM/SCR scanners with bounded concurrency. Offline-first; --online opt-in. JetBrains discovery stubbed for v1.1. 22 new tests (1296 total, was 1274). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
7bcf5fae9d
commit
6252e55700
33 changed files with 1849 additions and 20 deletions
123
plugins/llm-security/knowledge/ide-extension-threat-patterns.md
Normal file
123
plugins/llm-security/knowledge/ide-extension-threat-patterns.md
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
# IDE Extension Threat Patterns
|
||||
|
||||
Detection categories used by `scanners/ide-extension-scanner.mjs` (prefix `IDE`).
|
||||
Based on Koi Security / ExtensionTotal research 2024-2026 and VS Code / JetBrains official documentation.
|
||||
|
||||
Research brief: `/Users/ktg/.claude/plans/research-ide-extension-prescan.md`.
|
||||
|
||||
## Scope
|
||||
|
||||
MVP (v6.3.0): VS Code + forks (Cursor, Windsurf, VSCodium, code-server, Insiders, Remote-SSH).
|
||||
IntelliJ plugins deferred to v1.1 — JetBrains manual-review + opt-in signing reduces public case-study volume.
|
||||
|
||||
## 1. Blocklist Match (CRITICAL)
|
||||
|
||||
**Signal:** Extension ID (lowercased `publisher.name`) matches entry in `knowledge/top-vscode-extensions.json` `blocklist` array.
|
||||
|
||||
**Case:** TigerJack (11 malicious extensions, 17K+ installs). WhiteCobra (24 extensions, ~$500K crypto theft). VS Code Cryptojacking Campaign ("Mark H" impersonator, 1M+ installs). Known-malicious IDs are CRITICAL.
|
||||
|
||||
**Format:** `publisher.name@version` or `publisher.name@*` for any version.
|
||||
|
||||
**OWASP:** LLM03 (Supply Chain), ASI04.
|
||||
|
||||
## 2. Theme-with-Code (HIGH)
|
||||
|
||||
**Signal:** `package.json` `categories` includes `"Themes"` AND (`main` is truthy OR `activationEvents` non-empty).
|
||||
|
||||
**Case:** "A Wolf in Dark Mode" — the Material Theme malware. Popular theme with hidden malware under color-scheme. Pure themes require zero runtime code; any `main`/`activationEvents` on a theme is a strong red flag.
|
||||
|
||||
**OWASP:** LLM06 (Excessive Agency), ASI02.
|
||||
|
||||
## 3. Sideload Signal (HIGH unsigned, MEDIUM signed)
|
||||
|
||||
**Signal:** `extensions.json` entry has `metadata.source === "vsix"` (i.e. installed from file, not Marketplace).
|
||||
|
||||
**Rationale:** Marketplace signature verification and malware-scan bypassed for `.vsix`-file installs. Legitimate use cases exist (private extensions, dev testing), but high malware-ratio in observed incidents.
|
||||
|
||||
**Modifier:** If `.signature.p7s` file present in extension root → downgrade to MEDIUM (possibly Marketplace-downloaded .vsix).
|
||||
|
||||
**OWASP:** LLM03.
|
||||
|
||||
## 4. Broad Activation Surface (MEDIUM / LOW)
|
||||
|
||||
**Signal:** `package.json` `activationEvents` includes `"*"` (MEDIUM) or `"onStartupFinished"` (LOW).
|
||||
|
||||
**Rationale:** "Wants to run always" is a strong capability signal — necessary for a few legitimate tools (shell integrators, system monitors) but unusual for most extensions. Exemption: exact-match against top-100 list.
|
||||
|
||||
**Note:** VS Code 1.74+ no longer requires `activationEvents` for declarative `contributes` — absence of events is NOT suspicious.
|
||||
|
||||
**OWASP:** LLM06.
|
||||
|
||||
## 5. Typosquat (HIGH / MEDIUM)
|
||||
|
||||
**Signal:** Extension ID has Levenshtein distance ≤ 2 from a top-100 extension ID, excluding exact match.
|
||||
|
||||
- Distance 1 → HIGH
|
||||
- Distance 2 AND target is in top-50 → MEDIUM
|
||||
|
||||
**Case:** TigerJack aliases `ab-498`, `498`, `498-00` targeting popular AI / utility extensions. Publisher impersonation (e.g. `ms-pythom.pythom` vs `ms-python.python`). AI-assistant typosquats (`claude-code`, `codeium`, `cody`).
|
||||
|
||||
**OWASP:** LLM03.
|
||||
|
||||
## 6. Extension Pack Expansion (MEDIUM)
|
||||
|
||||
**Signal:** `package.json` `extensionPack` array contains ≥ 3 bundled extension IDs.
|
||||
|
||||
**Rationale:** Extension packs amplify trust chain — installing one extension installs N others, each of which brings its own risk surface.
|
||||
|
||||
**OWASP:** LLM03.
|
||||
|
||||
## 7. Dangerous Uninstall Hook (HIGH / LOW)
|
||||
|
||||
**Signal:** `package.json` `scripts["vscode:uninstall"]` exists AND references one of: `child_process`, `curl`, `wget`, `rm`, `powershell`, `iex`, `Invoke-Expression`, `Start-Process`.
|
||||
|
||||
**Rationale:** Uninstall scripts are a persistence hook — attacker can delay destructive payload to trigger on uninstall attempt. VS Code runs these scripts with the user's privileges.
|
||||
|
||||
**OWASP:** LLM06, ASI02.
|
||||
|
||||
## 8. Data Exfiltration Patterns (delegated)
|
||||
|
||||
Detected by reused scanners on extension bundled source:
|
||||
|
||||
- **Hardcoded webhooks** (Discord, Pipedream, webhook.site, Burp Collaborator, interactsh) → detected by NET scanner
|
||||
- **Base64-encoded C2 domains** → detected by ENT scanner
|
||||
- **Unicode Tag steganography** (GlassWorm pattern) → detected by UNI scanner
|
||||
- **Env var exfiltration** (`process.env.HOME`, SSH keys, `.aws/credentials`, `.env`) → detected by TNT scanner
|
||||
- **Clipboard / screen capture misuse** → detected by NET + TNT via API surface
|
||||
|
||||
**Cases:** GlassWorm (Unicode steganography + blockchain C2), MaliciousCorgi (AI-assistant data leaks), VS Code Cryptojacking (PowerShell download-and-execute), screen-capture malware ("Bitcoin Black", "Codo AI").
|
||||
|
||||
**OWASP:** LLM01 (Prompt Injection), LLM02 (Sensitive Disclosure), LLM03.
|
||||
|
||||
## 9. Nested npm Supply Chain (delegated)
|
||||
|
||||
Detected by SCR scanner on extension's bundled `package-lock.json` or flat `package.json` dependencies.
|
||||
|
||||
**Rationale:** A typical VS Code extension with `main` bundles 50–500+ transitive npm deps. VS Code Marketplace malware-scan does NOT inspect nested deps. Compromised npm packages (event-stream, rc, nx, ua-parser-js, lottie-player) flow into extensions automatically at build time.
|
||||
|
||||
**OWASP:** LLM03, ASI04.
|
||||
|
||||
## 10. Memory Poisoning via README / CHANGELOG (delegated)
|
||||
|
||||
Detected by MEM scanner on extension `README.md` and `CHANGELOG.md`.
|
||||
|
||||
**Rationale:** Extension README is displayed in VS Code when user inspects extension details. Prompt-injection payloads in README can poison co-located LLM assistants (Copilot, Claude Code) if the user asks about the extension.
|
||||
|
||||
**OWASP:** LLM01.
|
||||
|
||||
## Known Limitations
|
||||
|
||||
- No bytecode analysis of IntelliJ JARs (v1.1+)
|
||||
- No VSIX extraction (pass extracted directory instead)
|
||||
- No Marketplace API lookups without `--online` flag (publisher age, download count, verified status unavailable offline)
|
||||
- Profile-specific extension filtering not implemented (all installed extensions are scanned)
|
||||
- `.obsolete` file parsing not implemented (extensions marked obsolete are still scanned — harmless but redundant)
|
||||
- Real-time IDE hooks are out of scope (separate repo, planned)
|
||||
|
||||
## References
|
||||
|
||||
- Koi Security blog — https://koi.security/blog (GlassWorm, WhiteCobra, TigerJack, Material Theme, Cryptojacking, MaliciousCorgi, Screen-capture, Marketplace Takeover)
|
||||
- VS Code Extension Runtime Security — https://code.visualstudio.com/docs/configure/extensions/extension-runtime-security
|
||||
- VS Code Extension Manifest — https://code.visualstudio.com/api/references/extension-manifest
|
||||
- ExtensionTotal — https://extensiontotal.com (closed-source, compatible reference)
|
||||
- OSV schema — confirms no `VSCodeMarketplace` ecosystem (verified 2026-04-17)
|
||||
10
plugins/llm-security/knowledge/top-jetbrains-plugins.json
Normal file
10
plugins/llm-security/knowledge/top-jetbrains-plugins.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"_meta": {
|
||||
"source": "Stub for v1.1 — IntelliJ discovery deferred. See research brief §2, §4.",
|
||||
"count": 0,
|
||||
"last_updated": "2026-04-17",
|
||||
"purpose": "Typosquat detection seed for JetBrains plugins. To be populated in v1.1."
|
||||
},
|
||||
"jetbrains": [],
|
||||
"blocklist": []
|
||||
}
|
||||
118
plugins/llm-security/knowledge/top-vscode-extensions.json
Normal file
118
plugins/llm-security/knowledge/top-vscode-extensions.json
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
{
|
||||
"_meta": {
|
||||
"source": "VS Code Marketplace 'Most Popular' snapshot 2026-04-17. Manually curated from Marketplace and Koi/ExtensionTotal research.",
|
||||
"count": 100,
|
||||
"last_updated": "2026-04-17",
|
||||
"purpose": "Typosquat detection seed. IDs are lowercase publisher.name."
|
||||
},
|
||||
"vscode": [
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"ms-python.debugpy",
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"ms-azuretools.vscode-docker",
|
||||
"github.copilot",
|
||||
"github.copilot-chat",
|
||||
"github.vscode-pull-request-github",
|
||||
"github.remotehub",
|
||||
"anthropic.claude-code",
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.cpptools-extension-pack",
|
||||
"ms-vscode.cmake-tools",
|
||||
"twxs.cmake",
|
||||
"golang.go",
|
||||
"rust-lang.rust-analyzer",
|
||||
"vadimcn.vscode-lldb",
|
||||
"vscode-icons-team.vscode-icons",
|
||||
"zhuangtongfa.material-theme",
|
||||
"pkief.material-icon-theme",
|
||||
"ritwickdey.liveserver",
|
||||
"redhat.java",
|
||||
"vscjava.vscode-java-pack",
|
||||
"vscjava.vscode-java-debug",
|
||||
"vscjava.vscode-java-test",
|
||||
"vscjava.vscode-maven",
|
||||
"vscjava.vscode-gradle",
|
||||
"ms-vscode-remote.remote-ssh",
|
||||
"ms-vscode-remote.remote-ssh-edit",
|
||||
"ms-vscode-remote.remote-containers",
|
||||
"ms-vscode-remote.remote-wsl",
|
||||
"ms-vscode-remote.vscode-remote-extensionpack",
|
||||
"ms-dotnettools.csharp",
|
||||
"ms-dotnettools.csdevkit",
|
||||
"ms-dotnettools.vscode-dotnet-runtime",
|
||||
"ms-toolsai.jupyter",
|
||||
"ms-toolsai.jupyter-keymap",
|
||||
"ms-toolsai.jupyter-renderers",
|
||||
"ms-toolsai.vscode-jupyter-cell-tags",
|
||||
"ms-toolsai.vscode-jupyter-slideshow",
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"editorconfig.editorconfig",
|
||||
"codeium.codeium",
|
||||
"continue.continue",
|
||||
"saoudrizwan.claude-dev",
|
||||
"visualstudioexptteam.vscodeintellicode",
|
||||
"visualstudioexptteam.intellicode-api-usage-examples",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"formulahendry.auto-rename-tag",
|
||||
"formulahendry.auto-close-tag",
|
||||
"wix.vscode-import-cost",
|
||||
"christian-kohler.path-intellisense",
|
||||
"christian-kohler.npm-intellisense",
|
||||
"mhutchie.git-graph",
|
||||
"eamodio.gitlens",
|
||||
"donjayamanne.githistory",
|
||||
"waderyan.gitblame",
|
||||
"ms-vscode.live-server",
|
||||
"ms-vscode.powershell",
|
||||
"ms-vscode.vscode-typescript-next",
|
||||
"ms-vscode.vscode-node-azure-pack",
|
||||
"ms-vscode.makefile-tools",
|
||||
"ms-vscode.hexeditor",
|
||||
"hashicorp.terraform",
|
||||
"hashicorp.hcl",
|
||||
"redhat.vscode-yaml",
|
||||
"redhat.vscode-xml",
|
||||
"tamasfe.even-better-toml",
|
||||
"yzhang.markdown-all-in-one",
|
||||
"davidanson.vscode-markdownlint",
|
||||
"shd101wyy.markdown-preview-enhanced",
|
||||
"yzane.markdown-pdf",
|
||||
"unifiedjs.vscode-mdx",
|
||||
"mechatroner.rainbow-csv",
|
||||
"sonarsource.sonarlint-vscode",
|
||||
"snyk-security.snyk-vulnerability-scanner",
|
||||
"42crunch.vscode-openapi",
|
||||
"humao.rest-client",
|
||||
"rangav.vscode-thunder-client",
|
||||
"ms-kubernetes-tools.vscode-kubernetes-tools",
|
||||
"redhat.vscode-commons",
|
||||
"bmewburn.vscode-intelephense-client",
|
||||
"xdebug.php-debug",
|
||||
"dbaeumer.jshint",
|
||||
"esbenp.vscode-prettier",
|
||||
"svelte.svelte-vscode",
|
||||
"vue.volar",
|
||||
"angular.ng-template",
|
||||
"denoland.vscode-deno",
|
||||
"biomejs.biome",
|
||||
"oven.bun-vscode",
|
||||
"astro-build.astro-vscode",
|
||||
"styled-components.vscode-styled-components",
|
||||
"graphql.vscode-graphql",
|
||||
"graphql.vscode-graphql-syntax",
|
||||
"prisma.prisma",
|
||||
"bigonesystems.django",
|
||||
"ms-azuretools.vscode-azurefunctions",
|
||||
"ms-azuretools.vscode-azureresourcegroups",
|
||||
"amazonwebservices.aws-toolkit-vscode",
|
||||
"googlecloudtools.cloudcode",
|
||||
"orta.vscode-jest",
|
||||
"firsttris.vscode-jest-runner",
|
||||
"vitest.explorer",
|
||||
"ms-playwright.playwright",
|
||||
"cypress-io.vscode-cypress"
|
||||
],
|
||||
"blocklist": []
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue