To map an advisory to affected products fast, store every release SBOM in an index keyed by package URL, with the product, release, environment and shipped date alongside. A new advisory then becomes a lookup on one key and a version range check, not a search through repositories.
Definitions
A package URL (purl) is a standard string that names a package, such as an ecosystem, name and version. A reverse index is one that goes from a component to the places it is used, the opposite direction to an SBOM, which goes from a product to its components.
What each row holds
| Field | Why it matters |
|---|---|
| purl without version | The join key against advisories |
| Component version | For the range check |
| Product name | What customers recognise |
| Release version | What you will tell them to upgrade |
| Dependency type | Direct or transitive, to guide urgency |
| Shipped state | Built only, in staging, or released to customers |
| Shipped date | Whether a support window still covers it |
| SBOM source | The file and its hash, for audit |
Steps
- Generate an SBOM at build time for every release, in CycloneDX or SPDX.
- Validate it, and reject files with missing versions or identifiers.
- Normalise each component to a purl and split off the version.
- Write one row per component per release into the index.
- Mark the shipped state when the release actually reaches customers.
- Keep old rows. Customers run old releases, and your answer has to cover them.
For why identifiers matter more than names, see purl or CPE.
A worked lookup
Suppose an advisory names a package and says versions below a fixed version are affected. The lookup is:
select product, release, component_version
from index
where purl_base = 'pkg:npm/example-lib'
and shipped_state = 'released'
Then compare each version against the advisory range in the ecosystem's own version rules. Do not compare version strings as text, because "10" sorts before "9". Use a version library for the ecosystem.
Limits to state
An SBOM index tells you a component is present. It does not tell you the vulnerable function is called. That is a separate question, handled by reachability analysis or a documented justification in a VEX statement. Also note that an index is only as complete as the SBOMs behind it, so record gaps explicitly rather than hiding them.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how one component shows up across more than one project.
Quick check
Should the index include development dependencies?
Keep them, but tag them. A dev only dependency usually does not ship, which affects what you tell customers.
Why store the shipped state?
A component in a build that never reached customers needs a different message from one in a released product.
Safeguard's SBOM and dependency scanning and asset discovery produce this kind of inventory. A free scan will show it for one project.
Last reviewed: 19 October 2026.