ktg-plugin-marketplace/plugins/llm-security/docs/plans/ide-scan-url-support.md
Kjell Tore Guttormsen fb9eb79d17 docs(llm-security): research brief + URL-support plan for ide-scan
- jetbrains-research-brief.md: 29 sources, confidence 0.88 — input for v6.6.0 JetBrains/IntelliJ extension scanning. Covers plugin format, install paths per OS+product, Marketplace API, threat landscape (zero confirmed-malicious cases), check-mapping table, sandbox reuse verdict, risk register.
- ide-scan-url-support.md: retroactive plan doc for v6.4.0 URL-fetch feature.
2026-04-17 18:47:01 +02:00

7.6 KiB

Plan: /security ide-scan <url> — 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 <url>
  → 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<void>
      └─ 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 <marketplace|openvsx> (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