VEX SBOM Reference Normalizer
Problem
A VEX record identified only by a CVE can be applied to the wrong component when the same vulnerability affects multiple components. An externally updated VEX can also retain references that no longer exist in its SBOM.
This local VS Code extension provides one workflow: run one command to validate every (vulnerability ID, component reference) relationship and normalize affected-reference ordering without replacing an existing scanner.
Open a JSON document with this minimal envelope:
{
"sbom": {
"components": [
{ "bom-ref": "pkg:npm/example-a@1.0.0" },
{ "bom-ref": "pkg:npm/example-b@2.0.0" }
]
},
"vex": {
"vulnerabilities": [
{
"id": "CVE-2026-0001",
"affects": [
{ "ref": "pkg:npm/example-b@2.0.0" },
{ "ref": "pkg:npm/example-a@1.0.0" }
]
}
]
}
}
The MVP intentionally accepts this documented envelope rather than every CycloneDX document shape. Existing fields are preserved. Each vulnerability entry remains separate, so component-specific analysis fields are not merged merely because CVE IDs match.
Primary workflow
- Open the envelope as JSON in an Extension Development Host.
- Run
VEX: Validate and Normalize SBOM References from the Command Palette.
- If all references resolve uniquely, the active document is replaced with formatted JSON whose
affects entries are deduplicated and sorted by ref.
- If JSON is invalid, an SBOM
bom-ref is duplicated, or a VEX reference is missing from the SBOM, the document is unchanged and an error is shown.
The command reads only the active editor. It has no network access, telemetry, file-system traversal, account requirement, or background activation.
Extension Development Host check
Open this directory in VS Code, press F5 using a locally configured Extension Development Host, open tests/fixtures/success.json, and run the primary command. Confirm that the command succeeds. Repeat with tests/fixtures/unknown-reference.json and confirm that it reports an error without changing the document.
No launch configuration is included because hidden project directories are outside this build contract.
Local verification
From the project root, using an already available Node.js runtime:
node tests/success.test.js
node tests/failure.test.js
node tests/extension.test.js
node scripts/package.js --check
The tests use only Node.js standard-library modules. The packaging script performs a read-only readiness check and prints the deterministic package file list when run without arguments; it does not publish or create an archive.
Scope and limitations
- Only top-level
sbom.components are indexed.
- Every component must have a unique, non-empty
bom-ref.
- Every vulnerability must have a non-empty
id and an affects array.
- Empty
affects arrays are permitted because they do not claim a component relationship.
- The extension validates reference integrity; it does not determine exploitability, vulnerability status, or scanner correctness.
- Marketplace packaging and publication require separate approval and tooling.
See DECISIONS.md, SOURCE_RIGHTS.md, PRIVACY.md, and PUBLICATION_CHECKLIST.md before considering distribution.