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.
This commit is contained in:
parent
9ecd66929c
commit
fb9eb79d17
2 changed files with 442 additions and 0 deletions
140
plugins/llm-security/docs/plans/ide-scan-url-support.md
Normal file
140
plugins/llm-security/docs/plans/ide-scan-url-support.md
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
# 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
|
||||
|
||||
- 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue