skip to content

SBOM & VEX

You will learn what a bill of materials really contains, how SPDX and CycloneDX differ, and how VEX turns an inventory into a defensible answer about whether a CVE is exploitable here.

on this pageshow

explore

questions

page 1 of 2

Why keep a queryable SBOM estate instead of regenerating SBOMs when an advisory lands?

level: juniorimportance: must knowfreq 58%

answer

  1. the query is the product
  2. answer in seconds, not rebuilds
  3. describes what runs, not what compiles
  4. index coordinates, keep the document
  5. an empty result is not proof

basics

~20 s

A stored, queryable estate answers 'where do we run this component, and at what version' in seconds. Regenerating means rebuilding every service at its deployed commit, which is slow and describes today's source rather than what is actually running.

solid answer

~50 s

An SBOM describes one build of one artifact. An estate is every one of those documents ingested into a store, indexed by component coordinates and joined to the record of which artifact is deployed where. That join is the product: at 02:00 a bank with 900 services needs to know which of them run a given serialisation library and at which version, and it needs the answer before the next change window, not after a fleet-wide rescan. Regeneration is the wrong instrument for three reasons: repository scans describe the current branch rather than the running artifact, rebuilding at the deployed commit is often no longer possible, and the wall-clock cost across hundreds of services lands after the decision was due. The estate does that work once, at build time, and turns an incident question into a lookup.

go deeper

for a junior

Be ready to say plainly what an estate is for: one stored document per built artifact, indexed so you can ask where a component runs. Know that source scanning and a deployed-artifact inventory answer different questions.

for a middle

Explain the mechanics: what each record keys on, how the join from component to artifact to running service works, and why version comparison must follow the ecosystem's ordering rather than string order.

for a senior

Show the operating judgment. Say out loud how strong a positive answer is versus a negative one, and how you would qualify 'we do not run it' with the estate's coverage and record age before anyone repeats it externally.

for a principal

Own the framing that inventory is a capability with a running cost, not a one-off project. Be ready to argue where the money goes: build-time generation everywhere versus deeper indexing of a partial estate.

## What an estate is An SBOM (software bill of materials) is a machine-readable list of the components inside **one artifact, at one version**. On its own it is a file sitting next to a build. An *estate* is what you get when every one of those files is ingested into a store, indexed by component coordinates, and joined to a record of which artifact is actually deployed where. The estate, not the individual document, answers the question a security team is really asked: **where do we run this component, and at which version?** ## Why regeneration is the wrong instrument Picture a bank running roughly 900 services. Overnight, an advisory lands for a widely used serialisation library, and the on-call needs the exposed list before the morning change window. The instinctive move is to scan everything again. Three things go wrong: 1. **Repositories are not production.** A source scan describes the current main branch. What is running is an artifact built from some earlier commit, with dependency resolution that happened at that moment, in that build environment. The two lists differ, and the difference is exactly where incidents hide. 2. **Rebuilding at the deployed commit is often impossible.** Toolchains have moved, mirrors have drifted, credentials have rotated. Reproducing a nine-month-old build to ask it a question is a project, not a lookup. 3. **Time.** A rescan fleet across hundreds of repositories takes hours. The answer arrives after the decision had to be made. The estate pays that cost once, at build time, where the information is cheapest and most accurate, and then serves it as a query. ## What each record must carry A record ties three things together: - **The document** as it was received, stored verbatim, so you can re-derive facts later and so an auditor can see what you were told. - **The subject artifact's immutable identity** — the digest of the built image or package. Not a tag, which moves, and not a repository name, which produces many artifacts. - **A join to deployment**: artifact digest to environment, service, cluster or device fleet. A query then walks backwards: component coordinate to the documents that list it, to the artifact digests those documents describe, to the places those digests are running. ## Index coordinates, not display names Component names collide across ecosystems and change over time, so string matching produces both false negatives (a renamed package) and false positives (one word, two ecosystems). An ecosystem-qualified coordinate such as `pkg:npm/[email protected]` — the purl scheme — makes the match deterministic. Version comparison must follow the ecosystem's own ordering rules, because advisories describe **ranges**, not points; a naive lexical comparison puts `1.10.0` before `1.9.0` and quietly drops services from the answer. Keep both layers: the raw document for audit and reprocessing, and a normalised index for the query. You will change your mind about normalisation, and re-deriving from stored documents is far cheaper than re-collecting them. ## What the estate does not tell you Three limits, and confusing any of them for coverage is the classic mistake: - **It lists components, not exploitability.** That a vulnerable component is present says nothing about whether the vulnerable code is called or whether an attacker can reach it. That is a separate assessment on top of the inventory. - **It is only as complete as the documents in it.** Components a generator could not see are simply missing, and a missing component is invisible to every query you will ever run. - **It ages relative to what you deploy.** A document is a statement about a specific artifact version; it stops being useful the moment you run a different one. ## Positive and negative answers are not equally strong 'We run it in twelve services' is cheap to act on — you have twelve concrete things to look at, and each can be confirmed. 'We do not run it anywhere' is a much bigger claim: it asserts that the estate covers everything you deploy and that every document in it is complete. A junior answer that treats an empty result as proof of absence is the single most dangerous habit in this area. The honest formulation is 'no document in the estate lists it', paired with a statement of how much of the fleet the estate actually covers.

  • Why key each stored document to the artifact's digest rather than to a service or repository name?
    A repository produces many artifacts, and a tag can be moved to point at different content later. The digest is the one identifier that names exactly the bytes that are running, so the join from document to deployment stays true even after tags are reused or a service is renamed.
  • What breaks if you match components by display name instead of an ecosystem-qualified coordinate?
    You get both misses and noise. The same short name exists in several ecosystems, packages get renamed and republished, and vendors write the same product two different ways. A coordinate that carries the ecosystem, namespace, name and version makes the comparison deterministic, and lets version-range logic follow that ecosystem's ordering rules.
  • Your query returns twelve services. Why is that a weaker answer than it looks?
    It is a lower bound. It reflects the documents you hold, so anything the generators failed to record, any artifact with no document, and any record describing a version you no longer run is excluded from the count. Report the number together with the coverage and age of the records behind it.

A warehouse that logs what went into every crate as it is sealed can answer 'which crates hold this part' instantly. Opening every crate to look again is both slower and a different question.

saying these in an interview costs you the question

  • Says you can just rescan the repositories when an advisory drops
  • Treats an empty query result as proof the component is absent
  • Assumes the estate shows whether a component is exploitable
  • Confuses what the source branch contains with what is deployed
  • Indexes components by free-text name only

context

open as a page

A vendor gave you an SBOM once at contract signature — what is it still worth a year on?

level: juniorimportance: must knowfreq 55%

basics

~20 s

Little, as a live inventory. An SBOM describes one build at one moment, so after a year of vendor releases it need not match the version you run. It survives as a baseline and as proof the vendor can produce one.

open as a page

In VEX, what are the four product statuses a statement can assign, and what does each claim?

level: juniorimportance: must knowfreq 58%

basics

~10 s

VEX defines four statuses for a product-and-vulnerability pair: not_affected, affected, fixed, and under_investigation. They state whether a known vulnerability is actually exploitable in that product, not whether the flawed component is present.

open as a page

In an SBOM, how does a purl differ from a CPE as a component identifier?

level: juniorimportance: must knowfreq 70%

basics

~20 s

A purl is a coordinate computed from where a package actually came from: ecosystem, namespace, name, version. A CPE is a string from a curated dictionary that a human assigns, so it is often missing, duplicated or ambiguous.

open as a page

What does Syft do when you point it at a container image, and what does it not report?

level: juniorimportance: must knowfreq 68%

basics

~10 s

Syft unpacks the image's layers, runs per-ecosystem catalogers over the resulting filesystem to list installed packages, then serialises that list as SPDX or CycloneDX. It reports what is present, not whether anything is vulnerable.

open as a page

What are the seven data fields the NTIA minimum elements require in an SBOM?

level: juniorimportance: must knowfreq 70%

basics

~20 s

Supplier name, component name, version, other unique identifiers, dependency relationship, author of the SBOM data, and timestamp. Four identify the component, one records structure, two describe the document itself. A component hash is not among them.

open as a page

Why does an SBOM built from a project's lockfile differ from one built by scanning the shipped image?

level: juniorimportance: must knowfreq 60%

basics

~20 s

Each vantage observes something different. A lockfile lists what the package manager resolved for one ecosystem before the build; scanning the shipped image lists what actually landed on disk, including operating-system packages and files no manifest ever mentioned.

open as a page

Which SBOM is safer to act on: one exact about 12 direct dependencies, or one listing 800 transitives with a third of the versions wrong?

level: middleimportance: must knowfreq 64%

basics

~20 s

The narrow, exact one, provided it says it is narrow. An inaccurate list poisons every query built on it and you cannot tell which third is wrong. An incomplete list with a declared boundary lets you fill the rest in yourself.

open as a page

Which justification labels can back a VEX not_affected status, and why is one required?

level: middleimportance: must knowfreq 51%

basics

~10 s

Five labels: component_not_present, vulnerable_code_not_present, vulnerable_code_not_in_execute_path, vulnerable_code_cannot_be_controlled_by_adversary, and inline_mitigations_already_exist. One is required because a bare not_affected is an unauditable assertion nobody downstream can re-check.

open as a page

How do SPDX relationships and a CycloneDX dependencies array model the same component graph?

level: middleimportance: must knowfreq 62%

basics

~20 s

SPDX records typed edges in a relationships array — CONTAINS, DEPENDS_ON, DESCRIBES and many more — between SPDXIDs. CycloneDX records one kind of edge, ref to dependsOn, between bom-ref values, and expresses containment by nesting components instead of by naming the edge.

open as a page

A vendor's SBOM for a payment terminal image lists 41 components; your own inspection of that image finds around 300. What do you do?

level: seniorimportance: must knowfreq 56%

basics

~20 s

Treat the number as a question, not a finding. Confirm both views describe the same artefact digest, read what the document declares it covers, then bucket the extras: OS base layer, build-only, vendored code. The undeclared part of the gap is the defect.

open as a page

Your firmware SBOM meets every NTIA minimum element — why can't it tell a hospital whether the device is exploitable?

level: seniorimportance: must knowfreq 58%

basics

~20 s

Because the minimum elements record what is inside the build and nothing else. They carry no reachability, configuration or exploitability claim and no account of how the artifact was produced, so a component matching an advisory is a candidate for investigation, not a verdict.

open as a page

What does a NOASSERTION supplier field in an SBOM tell a consumer?

level: juniorimportance: should knowfreq 52%

basics

~20 s

A NOASSERTION supplier field means the document's author explicitly declined to name the supplier, not that none exists. The component and version still count as inventory, but the document cannot tell you its origin or who to ask for a fix.

open as a page

In an SPDX SBOM, what is the difference between NOASSERTION and NONE in a license field?

level: juniorimportance: should knowfreq 45%

basics

~20 s

NONE is a positive claim that nothing is there: the producer looked and found no license. NOASSERTION means the producer makes no claim at all, whether undetermined or withheld. Neither is the same as an empty field.

open as a page

A supplier reuses one CycloneDX serialNumber across three releases. How should your estate key records?

level: middleimportance: should knowfreq 45%

basics

~20 s

Key on the identity you can verify yourself: the digest of the artifact the document describes. Treat supplier-supplied identifiers as metadata, store ingests append-only, and flag a repeated identifier over different subjects instead of overwriting the earlier record.

open as a page

What contract terms turn a supplier's promise of an SBOM into an enforceable obligation?

level: middleimportance: should knowfreq 44%

basics

~20 s

Name the artifact and machine-readable format, require one document per released version, set a deadline triggered by new advisories, secure retention and tooling rights, and attach a remedy or audit right when delivery is missed.

open as a page

Why can a distro-rebuilt package version like 1.1.1n-0+deb11u3 produce a false vulnerability match?

level: middleimportance: should knowfreq 52%

basics

~10 s

Distributions backport security fixes into an older upstream version and mark the rebuild with their own revision suffix. A matcher reading only the upstream part flags a package whose fix is already in.

open as a page

cdxgen, Syft and Trivy can all emit CycloneDX - what does a generator's native model change?

level: middleimportance: should knowfreq 45%

basics

~20 s

Every generator keeps its own component model and projects it onto whichever format you ask for. cdxgen models to CycloneDX directly; Syft and Trivy export to either format, so spec fields their model never captured come out empty.

open as a page

Beyond the data fields, what else do the NTIA minimum elements for an SBOM require?

level: middleimportance: should knowfreq 46%

basics

~20 s

Two further categories: automation support — a machine-readable format that can also be generated automatically, such as SPDX, CycloneDX or SWID — and practices and processes: frequency, depth, declaring known unknowns, distribution and delivery, access control, and accommodation of mistakes.

open as a page

Why does an SBOM scan of a scratch image holding one static Go binary find almost nothing?

level: middleimportance: should knowfreq 45%

basics

~20 s

Filesystem analysis identifies components from evidence — package databases, manifests, shared libraries. A scratch image with one statically linked binary has none of that, because every dependency was compiled into the executable, so the scan reports an almost empty document.

open as a page

Your SBOM estate holds device-supplier documents of wildly different ages. How do queries expose staleness?

level: seniorimportance: should knowfreq 50%

basics

~20 s

An inventory document goes stale relative to what you deploy, not with age alone. Compare each record's subject version against the running version, date claims by the producer's stated creation time rather than your ingestion time, and keep no-record distinct from mismatched.

open as a page

An industrial PLC supplier refuses to give any SBOM and offers a security assurance letter — how do you read that?

level: seniorimportance: should knowfreq 37%

basics

~20 s

As information about the supplier. Find out whether they will not or cannot produce one: inability predicts slow advisory answers too. A letter carries no components, so pair it with checkable commitments and compensating controls around the device.

open as a page

Which VEX justification fits an appliance whose vulnerable XML parser ships only inside an offline migration tool?

level: seniorimportance: should knowfreq 41%

basics

~10 s

vulnerable_code_not_in_execute_path, scoped to the appliance firmware. The parser is inside the image you shipped, so component_not_present is false and your own inventory for that image would disprove it in public.

open as a page

Your build shades a JSON parser into your own namespace — how do you keep it visible in your SBOM?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Generate the SBOM from the resolved dependency graph at build time, before relocation erases the coordinates, and ship it with the artifact. Once classes are relocated into your namespace, no consumer can recover the parser's identity by inspecting what you published.

open as a page

What is lost when you convert a CycloneDX BOM with an inline vulnerabilities array into SPDX?

level: seniorimportance: should knowfreq 38%

basics

~20 s

The vulnerability records themselves. SPDX 2.x has no object to hold a vulnerability record, so a converter either drops the array or degrades it to an external link. Pedigree, composition-completeness and service entries have no clean home either.

open as a page

Your CI worker image's SBOM lists OS packages but no Ruby gems - how do you diagnose it?

level: seniorimportance: should knowfreq 42%

basics

~20 s

The two halves come from different analyzers. The OS half read the distribution package database; the gem half found no evidence it recognises and emitted nothing without failing. Find where the gems really live, and generate there.

open as a page

Why does a manifest-based SBOM miss a compression library vendored into a C++ service's source tree?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Manifest and lockfile parsing records declarations, and vendored source declares nothing — it is just files in your repository. The component ships in the binary while the document says it is not there, which is worse than an admitted gap.

open as a page

A supplier's SPDX BOM declares a compound license expression; your ingestion stores one license name — what breaks?

level: middleimportance: nice to knowfreq 33%

basics

~20 s

An SPDX license expression is a grammar, not a label: AND means all apply, OR means a choice, WITH attaches an exception. Storing one name picks a branch and drops the exception, so your record no longer matches the supplier's.

open as a page

Your nightly image's SBOM changes week to week with no code change - what explains it?

level: middleimportance: nice to knowfreq 33%

basics

~20 s

Three things can move under you: the artifact, because a floating base-image tag now resolves to a different digest; the generator, because a new version added or renamed catalogers; and the options, because a different scope counts different layers.

open as a page

In an SBOM, how does the NTIA 'supplier name' field differ from 'author of SBOM data'?

level: middleimportance: nice to knowfreq 30%

basics

~20 s

Supplier names the entity that created or distributed the component. Author of SBOM data names whoever produced these entries — often a downstream integrator that regenerated or merged documents, not the supplier. The timestamp dates the document, not the build.

open as a page

showing 1–30 of 36