# Plan: `/security ide-scan ` — ekstern URL-support (v6.4.0) **Status:** Planlagt **Mål-release:** v6.4.0 **Skrevet:** 2026-04-17 **Motivasjon:** Hovedbruk av `ide-scan` er pre-installasjonsverifisering — sjekk en extension FØR du installerer den. Dagens scanner krever at extension allerede er installert (`~/.vscode/extensions/`) eller at target peker til en allerede utpakket mappe. ## Støttede URL-typer | Type | Eksempel | Fetch-strategi | |------|----------|----------------| | VS Code Marketplace | `https://marketplace.visualstudio.com/items?itemName=anthropic.claude-code` | POST til `/_apis/public/gallery/.../vspackage` (undokumentert men stabilt mønster) | | OpenVSX | `https://open-vsx.org/extension/anthropic/claude-code` | Offentlig API: `/api/{pub}/{name}/{version}/file/{pub}.{name}-{version}.vsix` | | Direkte .vsix | `https://example.com/ext.vsix` | Enkel GET | | GitHub repo | `https://github.com/anthropic/claude-code` | Bygg fra source? (se "Åpen beslutning") | ## Sikkerhetsmodell VSIX er en ZIP-fil. Extraction er den største angrepsflaten — vi må forhindre: - **Zip-slip** (`../../etc/passwd` i filnavn) - **Symlink-angrep** (VSIX-spec tillater ikke symlinks, men parser må avvise dem) - **Zip-bomber** (10MB komprimert → 100GB ukomprimert) - **Path traversal** via absolutte paths i entry-navn - **Unicode-normalization-angrep** (NFC/NFD-forskjeller som omgår path-checks) **Caps:** - Max komprimert størrelse: 50MB (VSIX over dette er mistenkelig) - Max ukomprimert størrelse: 500MB - Max entries: 10 000 - Max depth: 20 - Max expansion ratio: 100x (sum ukomprimert / sum komprimert) ## Arkitektur ``` /security ide-scan → commands/ide-scan.md (dispatcher) → bin/llm-security.mjs eller direkte → scanners/ide-extension-scanner.mjs ├─ url-detect: pattern-match for supported URL typer ├─ lib/vsix-fetch.mjs (NY) │ ├─ detectUrlType(url) → 'marketplace' | 'openvsx' | 'vsix' | 'github' │ ├─ fetchMarketplaceVsix(publisher, name) │ ├─ fetchOpenVsxVsix(publisher, name, version) │ ├─ fetchDirectVsix(url) │ └─ returnerer { buffer, url, contentType, size, sha256 } ├─ lib/zip-extract.mjs (NY) │ ├─ zero-dep ZIP-parser (central directory + local file header + deflate via node:zlib) │ ├─ validateEntry(name) — reject zip-slip, absolute paths, symlinks │ └─ extractToDir(buffer, tempDir, caps) → Promise └─ Eksisterende scan-pipeline mot tempDir ``` ## Implementasjonssteg ### Steg 1: `lib/vsix-fetch.mjs` (~150 linjer) - Bruk `fetch()` (Node 18+, zero deps) - Kun HTTPS, ingen redirect til HTTP - Timeout 30s, size-cap 50MB via streaming + abort - TLS-verifisering default (ikke tillat `--insecure`) - SHA-256-beregning underveis - Marketplace: POST-payload + header `Accept: application/octet-stream` — se knowledge/marketplace-api-notes.md (lag den) - OpenVSX: offentlig dokumentert API, enklest - Returnerer `{ buffer, sourceUrl, sha256, publisher, name, version }` ### Steg 2: `lib/zip-extract.mjs` (~250 linjer) - Parse End of Central Directory (EOCD) fra slutten - Les Central Directory headers → entries-array - For hver entry: les Local File Header, inflate med `node:zlib.createInflateRaw` - Valideringer PER entry (før skriv): - Normaliser path (remove `.`, resolve `..`, reject absolute) - Avvis hvis path escaper targetDir (via `path.resolve` + prefix-sjekk) - Avvis `external_attr` som indikerer symlink (0xA000 flag) - Akkumulere expansion ratio, abort hvis > 100x - Kun filer, ingen dirs (opprett dirs on-the-fly) - Tests: fixtures med kjente angrep (zip-slip fixture, symlink fixture, bomb fixture) ### Steg 3: Utvid `ide-extension-scanner.mjs` - Early-detect: `if (target.startsWith('http')) → fetch + extract → scan(tempDir)` - Ny option: `--online-source ` (default: auto-detect fra URL) - Cleanup: `try/finally` med `rm(tempDir, { recursive: true, force: true })` - Error-mapping: network errors → "unreachable", signature fail → "tamper", zip fail → "malformed" - Envelope.meta.source: `{ type: 'url', url, sha256, publisher, name, version }` ### Steg 4: CLI + command-dispatcher - `bin/llm-security.mjs`: passthrough, ingen endring nødvendig (target er allerede første arg) - `commands/ide-scan.md`: oppdater eksempler + flagg-dokumentasjon ### Steg 5: Tester (~20 nye) - Mock HTTP-server (node:http) for fetch-tester - Fixture-VSIX: bygg en fra `tests/fixtures/ide-extensions/root-benign/publisher.benign-ext-1.0.0/` via `zip -r` i test-setup - Zip-slip fixture: VSIX med `../../etc/passwd` entry - Zip-bomb fixture: 1KB komprimert → 10GB ukomprimert (syntetisk) - Integration: OpenVSX-mock → fetch → scan → envelope - Unit: detectUrlType, extractToDir med caps ### Steg 6: Knowledge + docs - `knowledge/marketplace-api-notes.md`: dokumenter undokumenterte Marketplace-endpoints + stabilitet - `docs/ide-scan-url-usage.md`: eksempler for pre-install-workflow - CHANGELOG: v6.4.0-seksjon - Plugin README: legg til URL-eksempler på `/security ide-scan` - Rot-README: oppdater til v6.4.0 (hvis tests passerer 1300+ og URL-support er feature-highlight) ### Steg 7: Versjon + ship - `npm run bump -- 6.4.0` - Test-suite grønn - Smoke test: `llm-security ide-scan https://open-vsx.org/extension/anthropic/claude-code` — skal funke (åpen API) - Commit + push til Forgejo (main, pre-autorisert) ## Åpne beslutninger (diskuter i neste sesjon) 1. **GitHub repo som URL** — skal vi bygge extension fra source? Legger til build-step (node+npm installert + `npm install + vsce package`). Stor kompleksitet. Foreslår: IKKE støtt GitHub i v6.4.0 — bare VSIX-baserte kilder. 2. **Marketplace API-stabilitet** — undokumentert endpoint kan endres. Fall-back: OpenVSX-lookup hvis Marketplace feiler (de fleste Marketplace-extensions finnes også på OpenVSX). 3. **Cache** — bør vi cache nedlastede VSIX i `~/.cache/llm-security/vsix/` (med SHA-256 som key, 7-dagers TTL)? Sparer båndbredde ved gjentatte scans. JA — enkelt og skru-av-bart via `--no-cache`. 4. **Signatur-verifisering av VSIX** — VS Code har begynt å signere publisher uploads (`.signature.p7s` i VSIX). Bør vi verifisere? Krever X.509-parsing (Node har `node:crypto` men P7S er kompleks). Foreslår: v6.5.0, ikke v6.4.0. ## Akseptansekriterier - [ ] `llm-security ide-scan https://open-vsx.org/extension/anthropic/claude-code` returnerer envelope med korrekt publisher/name/version - [ ] `llm-security ide-scan https://marketplace.visualstudio.com/items?itemName=anthropic.claude-code` fungerer (forutsatt endpoint er stabilt) - [ ] Zip-slip-fixture resulterer i BLOCK-verdict, ingen filer skrevet utenfor tempDir - [ ] Zip-bomb-fixture stoppes ved 100x expansion ratio - [ ] Temp-dir renses i alle exit-paths (success, error, abort) - [ ] Nettverksfeil → tydelig feilmelding, ikke stack trace - [ ] Scan av ekte Marketplace-extension (f.eks. `ms-python.python`) fullfører på < 30s på normal forbindelse - [ ] Test-suite 1300+ grønn ## Estimat - Kode: ~600 linjer (vsix-fetch: 150, zip-extract: 250, integrasjon: 100, tester: 100) - Tid: 1 fokusert sesjon med auto mode - Risiko: Moderat — zip-extraction er kjent angrepsvektor, trenger grundige tester. Fetch er enkelt. ## Referanser - OpenVSX API: https://open-vsx.org/swagger-ui - VS Code Marketplace (undokumentert): https://github.com/microsoft/vscode-vsce/blob/main/src/publish.ts - ZIP format spec: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT - Zip-slip CVE: https://snyk.io/research/zip-slip-vulnerability - Node fetch + streaming: https://nodejs.org/api/globals.html#fetch