Pre-installation verification of VS Code extensions via URL — fetch a remote VSIX, extract it in a hardened sandbox, and run the existing IDE scanner pipeline against it. No npm dependencies. Sources: - VS Code Marketplace (publisher.gallery.vsassets.io direct download) - OpenVSX (open-vsx.org official API) - Direct .vsix HTTPS URLs Defenses: - HTTPS-only, TLS verified, manual redirect with per-source host whitelist - 30s total timeout via AbortController - 50MB compressed cap, 500MB uncompressed, 100x expansion ratio - Zero-dep ZIP extractor: zip-slip, absolute paths, drive letters, NUL bytes, symlinks (Unix mode 0xA000), depth limits, ZIP64 rejected, encrypted rejected - SHA-256 streamed during fetch, surfaced in meta.source - Temp dir cleanup in all paths (try/finally) Files: - scanners/lib/vsix-fetch.mjs (HTTPS fetcher, host whitelist, streaming SHA-256) - scanners/lib/zip-extract.mjs (zero-dep parser with hardening caps) - knowledge/marketplace-api-notes.md (endpoint reference) - 3 test files (48 tests added: vsix-fetch, zip-extract, ide-extension-url) Tests: 1296 → 1344 (all green). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
84 lines
3.1 KiB
Markdown
84 lines
3.1 KiB
Markdown
# VS Code Marketplace + OpenVSX API notes
|
|
|
|
Reference notes for `scanners/lib/vsix-fetch.mjs`. These endpoints are used to
|
|
download VSIX packages for `/security ide-scan <url>` (v6.4.0).
|
|
|
|
## VS Code Marketplace
|
|
|
|
**Status:** Undocumented but stable. Used by the `vsce` CLI and by VS Code itself.
|
|
|
|
### Direct VSIX download (the URL we use)
|
|
|
|
```
|
|
https://{publisher}.gallery.vsassets.io/_apis/public/gallery/publisher/{publisher}/extension/{name}/latest/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage
|
|
```
|
|
|
|
- `{publisher}` and `{name}` come from the `itemName=publisher.name` query
|
|
parameter on `https://marketplace.visualstudio.com/items`.
|
|
- `latest` resolves to the most recent stable version. Specific versions can
|
|
be requested by replacing `latest` with `<version>`.
|
|
- The response is a ZIP (VSIX) with `Content-Type: application/octet-stream`.
|
|
- May redirect to `*.gallerycdn.vsassets.io`. Our fetcher allows redirects only
|
|
to that host family, never to arbitrary hosts.
|
|
|
|
### `extensionquery` (not used here, listed for completeness)
|
|
|
|
```
|
|
POST https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery
|
|
Headers:
|
|
Accept: application/json;api-version=3.0-preview.1
|
|
Content-Type: application/json
|
|
Body:
|
|
{ "filters": [{ "criteria": [{ "filterType": 7, "value": "publisher.name" }] }],
|
|
"flags": 914 }
|
|
```
|
|
|
|
This returns metadata (versions, publisher info, statistics) but is heavier
|
|
than the direct download, and parsing the response shape is brittle. We keep
|
|
the direct download path for v6.4.0.
|
|
|
|
### Stability risk
|
|
|
|
Microsoft has changed Marketplace APIs in the past without warning. Mitigation:
|
|
|
|
- Fall back to OpenVSX when both options exist (most extensions are mirrored).
|
|
- Document the endpoint here so that breakage can be diagnosed quickly.
|
|
- All callers receive a single `Error` with a descriptive message — no stack
|
|
traces leak through to the scanner envelope.
|
|
|
|
## OpenVSX (Eclipse Foundation)
|
|
|
|
**Status:** Officially documented at https://open-vsx.org/swagger-ui.
|
|
|
|
### Resolve "latest" version
|
|
|
|
```
|
|
GET https://open-vsx.org/api/{publisher}/{name}/latest
|
|
```
|
|
|
|
Returns JSON. We extract `.version` and use it for the next request.
|
|
|
|
### Direct VSIX download
|
|
|
|
```
|
|
GET https://open-vsx.org/api/{publisher}/{name}/{version}/file/{publisher}.{name}-{version}.vsix
|
|
```
|
|
|
|
Returns the raw VSIX. May redirect to `openvsxorg.blob.core.windows.net`.
|
|
|
|
## Caps & defenses (shared by all sources)
|
|
|
|
- TLS verification enabled (no `--insecure` opt-in).
|
|
- HTTPS only. Plain HTTP is rejected at `detectUrlType` and at fetch time.
|
|
- Manual redirect handling. Allowed hosts whitelisted per source type.
|
|
- 30-second total timeout via `AbortController`.
|
|
- 50MB compressed VSIX cap. Streaming reader aborts when cap exceeded.
|
|
- SHA-256 computed during streaming for `meta.source.sha256`.
|
|
|
|
## What is NOT supported (v6.4.0)
|
|
|
|
- GitHub repo URLs — would need `npm install` + `vsce package` build step.
|
|
- VS Code `code:` protocol URIs.
|
|
- VSIX signature verification (`.signature.p7s`). Deferred to v6.5.0.
|
|
- ZIP64 archives. Real VSIX never approaches the 4 GB threshold.
|
|
- Encrypted ZIP entries (general-purpose flag bit 0).
|