Skip to content

feat: add vscode-extensions-cataloger (anchore/grype#2851)#4864

Open
ChrisJr404 wants to merge 1 commit into
anchore:mainfrom
ChrisJr404:add-vscode-extension-cataloger
Open

feat: add vscode-extensions-cataloger (anchore/grype#2851)#4864
ChrisJr404 wants to merge 1 commit into
anchore:mainfrom
ChrisJr404:add-vscode-extension-cataloger

Conversation

@ChrisJr404

Copy link
Copy Markdown
Contributor

This is the syft side of anchore/grype#2851 — a cataloger for installed Visual Studio Code extensions, sourced from the user-extensions registry file .vscode/extensions/extensions.json (and the matching .vscode-server/... path used by remote / SSH / Codespaces installs, which has the identical schema).

@spiffcs marked the issue as good-first-issue and noted SBOM coverage of developer tooling installed outside the distro / admin path is the value here. @westonsteimel correctly flagged that the GHSA advisories for VSCode aren't currently structured for direct package-name matching, so grype won't surface vulnerabilities for these extensions today — but the catalog half is still useful on its own and unblocks any future matcher work.

What's added

File Purpose
syft/pkg/cataloger/vscode/cataloger.go New vscode-extensions-cataloger registered against **/.vscode/extensions/extensions.json and **/.vscode-server/extensions/extensions.json
syft/pkg/cataloger/vscode/parse_extensions_json.go JSON decoder + pkg.Package materialization
syft/pkg/cataloger/vscode/parse_extensions_json_test.go Realistic + malformed fixture tests, splitExtensionID unit tests
syft/pkg/cataloger/vscode/testdata/... Three fixture trees (extensions / malformed / empty)
syft/pkg/vscode.go New pkg.VscodeExtensionEntry metadata type
syft/pkg/type.go New VscodeExtensionPkg with PURL type \"vscode-extension\"
internal/task/package_tasks.go Task factory registration with selectors directory, installed, image, vscode, vscode-extension, editor
Generated: capabilities.yaml, packagemetadata, schema-16.1.4.json Standard regen artifacts

Per-extension pkg.Package shape

  • Name: canonical <publisher>.<name> id, e.g. github.copilot-chat. Matches what code --install-extension accepts and what settings.json references.
  • Version: installed version (semver)
  • Type: pkg.VscodeExtensionPkg (vscode-extension)
  • PURL: pkg:vscode-extension/<publisher>/<name>@<version>
  • Metadata: pkg.VscodeExtensionEntry with publisher, marketplace UUID, publisherDisplayName, isBuiltin, isPreReleaseVersion, and targetPlatform (when not the cross-platform sentinel \"undefined\")

PURL choice

There's no formally registered PURL type for VSCode extensions in the upstream package-url spec yet. I went with pkg:vscode-extension/... because:

  • it's the descriptive form already used in community SBOM tooling
  • vscode-extension is unambiguous (won't collide with hypothetical future vscode-* types)
  • if the spec eventually standardizes a different name, the change is local to syft/pkg/type.go and one helper

Open to renaming to pkg:vscode/... (shorter) or pkg:generic/...?type=vscode-extension (most conservative) if maintainers prefer one of those.

Tests

Test What it covers
TestParseExtensionsJSON Marketplace install, builtin extension, scoped publisher with multi-segment name (ms-vscode.cpptools-extension-pack), prerelease flag, target-platform handling
TestParseExtensionsJSON_Malformed Mixed-validity input: only valid records emitted, malformed ones (missing dot, leading/trailing dot, no version) silently skipped
TestSplitExtensionID Edge cases for the <publisher>.<name> parser — first-dot delimiter, multi-dot names, empty / leading-dot / trailing-dot inputs
Existing TestTypeFromPURL (extended) Ensures the new type round-trips through PURL

Test plan

  • go test ./syft/pkg/cataloger/vscode/... passes
  • go test ./syft/pkg ./internal/packagemetadata ./internal/task passes
  • go generate ./internal/... produces only intended diffs (capabilities + metadata generated; reverted the unrelated whitespace churn gofmt -s -w introduces in internal/spdxlicense/license_list.go)
  • cd internal/jsonschema && go run . cleanly emits the new schema-16.1.4.json (additive bump per SchemaVer; only adds JavascriptBunLockEntry ... wait no, only adds VscodeExtensionEntry)
  • DCO signed

Catalogs Visual Studio Code extensions installed in user profiles by
parsing the registry file at .vscode/extensions/extensions.json (and
the equivalent .vscode-server path for remote/SSH/Codespaces installs).

This lands the syft side of anchore/grype#2851. Each extension becomes
a pkg.Package with:

- Name = canonical "<publisher>.<name>" id (matches what `code
  --install-extension` accepts and what settings.json references)
- Version = installed version
- Type = new pkg.VscodeExtensionPkg ("vscode-extension")
- PURL = pkg:vscode-extension/<publisher>/<name>@<version>
- Metadata = new pkg.VscodeExtensionEntry with publisher, marketplace
  uuid, isBuiltin, isPreReleaseVersion, and targetPlatform when set

There is no formally registered package-url type for VSCode extensions
in the upstream PURL spec yet; "vscode-extension" is the descriptive
form already used in community SBOM tooling. If/when the spec adopts a
different name, the change is local to syft/pkg/type.go and the
cataloger's packageURL helper.

Selectors: directory, image, installed, vscode, vscode-extension,
editor — so default scans pick it up without explicit opt-in.

Tests cover:
- a realistic extensions.json with marketplace, builtin, prerelease,
  scoped publisher, and platform-specific entries
- a malformed fixture mixing valid and invalid records (missing dot in
  id, leading/trailing dot, missing version) — only valid records are
  emitted, malformed ones silently skipped
- splitExtensionID unit tests covering edge cases

Worth noting: as @westonsteimel pointed out on the issue, the GHSA
advisories for VSCode are not currently structured for direct package-
name matching, so grype won't surface vulns for these extensions today.
The cataloger output is still useful on its own for SBOM coverage of
developer tooling that bypasses distro/admin package controls.

Signed-off-by: Chris (ChrisJr404) <11917633+ChrisJr404@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant