Component identifiers

The whole arrangement rests on an apparently trivial operation: linking a component in your SBOM to a published vulnerability. That is where the reliability of everything else is decided, and where most arrangements fail.

The available identifiers

PURL — package URL

A canonical per-ecosystem identifier, of the form pkg:type/namespace/name@version?qualifiers.

pkg:maven/org.example/http-client@5.3.1
pkg:npm/%40scope/package@1.2.3
pkg:pypi/requests@2.32.3
pkg:golang/github.com/example/mod@v1.4.0
pkg:deb/debian/openssl@3.0.11-1~deb12u2?arch=amd64

Always prefer it. A PURL is deterministic: it describes a package in a given ecosystem unambiguously, which makes correlation exact.

CPE — common platform enumeration

The NVD’s historical identifier, of the form cpe:2.3:a:vendor:product:version:....

Necessary to query the NVD, but structurally imprecise: the vendor/product pair is entered by hand, with spelling variants, homonyms and missing entries. It is the number-one cause of false positives and false negatives.

SWID

Standardised software identification tags, little used outside certain enterprise environments.

Cryptographic hashes

SHA-256 or equivalent, computed over the artefact. They do not identify a component in a registry, but they tie the inventory to the real object — which is what makes an SBOM evidence rather than a statement.

OmniBOR / GitOID

Content-derived identifiers allowing fine traceability down to the file. Emerging; worth watching where file-level granularity is needed.

The matching problem

Three typical failures:

Failure Example Consequence
False positive by homonymy Two products from different vendors sharing a name An alert about a component you do not have
False negative by missing CPE A vulnerability published with no CPE, or a wrong one A real vulnerability goes undetected
False positive by version A distribution backports a fix without changing the upstream version number An alert about a version that is in fact fixed

The third case is particularly painful: Linux distributions backport heavily while keeping the upstream version number. A scanner unaware of the distribution reports hundreds of already fixed vulnerabilities.

How to make it reliable

  1. Require a valid purl on every component, and fail the build below a coverage threshold.
  2. Query per-ecosystem databases — OSV first — rather than correlating everything by CPE.
  3. Populate distribution metadata where the component comes from a system package, so the tool applies the right fix database.
  4. Keep hashes, so it is possible to verify later that an SBOM really describes the shipped artefact.
  5. Document matching exceptions in a VEX rather than suppressing the alert: a suppressed alert disappears, a documented one remains traceable.

The quality of identifiers directly determines the volume of noise teams will face. It is an infrastructure investment, not a tool setting: see Managing false positives.