Automating SBOM and VEX in Your Build Pipeline

Key takeaways
- Bind every SBOM to an image digest, not a tag — a rebuilt tag silently invalidates a stored inventory.
- Generate in CI from build context, and fail the build when a document does not validate against its schema.
- An inventory without an exploitability statement increases triage load, because every listed component is something a scanner can flag.
- Backported fixes are the main case VEX resolves, since the patched package keeps its original version string.
- None of this lowers your vulnerability count — it stops you re-triaging findings you already resolved.
Generating an SBOM once, by hand, produces a document that is wrong by the next rebuild. The useful version is automated: one inventory per image digest, emitted by CI, stored beside the artifact, and accompanied by a machine-readable exploitability statement so your scanner stops re-reporting things you already fixed. That pairing — inventory plus verdict, both generated, both attached — is what turns a compliance artifact into something your pipeline actually uses.
This is the operational half of the problem. If you need the one-off mechanics first, how to generate an SBOM for a container image covers the single-run case, and 10 best SBOM generation tools covers tool selection. This post is about what runs every build.
Why a manually generated SBOM is wrong almost immediately
An SBOM describes one exact set of bytes. Rebuild the image — new base layer, patched package, different transitive resolution — and the document describes something that no longer exists.
That has three consequences teams discover late:
- A release-tagged SBOM is ambiguous. If app:1.4.2 was rebuilt, the tag points somewhere new and the stored document may describe the old manifest.
- Scanning a running container is not a substitute. The build context is gone, so you recover an approximation of what is installed rather than a record of what was assembled.
- An out-of-date inventory fails the one job it has. When an advisory lands, the question is which builds contain the affected component — answerable only from inventories that were accurate when each build shipped.
The fix is structural rather than procedural: bind generation to the build, and bind the document to the digest.
What "automated" actually has to mean
Four properties separate a pipeline that generates SBOMs from one that merely can.
| Property | What it means | What breaks without it |
|---|---|---|
| Per-digest, not per-tag | One document for each manifest digest | Rebuilt tags silently invalidate stored inventories |
| Generated in CI | Emitted during the build, from build context | Post-hoc scans miss build-time resolution detail |
| Stored as a registry attachment | Travels with the artifact | Documents drift into a bucket nobody can map back |
| Schema-validated in CI | A malformed document fails the build | Consumers discover the problem, not you |
The format question matters less than any of these. Both major formats express components, versions, identifiers and relationships, and both attach to a digest: CycloneDX is an OWASP flagship project published as ECMA-424, and SPDX is governed by its own community. Pick the one your scanner, registry or customer accepts, generate it consistently, and convert only at the boundary where someone demands the other.
Why SBOM automation is incomplete without VEX
An inventory says what is present. It does not say what matters. Left alone, a complete SBOM increases the number of findings your team has to explain, because every component in it is a component a scanner can match against a vulnerability record.
The missing half is a machine-readable exploitability statement. CISA defines four statuses — not_affected, affected, fixed, under_investigation — and requires a justification whenever a producer claims not_affected (CISA). That justification requirement is what distinguishes a structured claim from an unexplained dismissal.
The case this resolves most often is backporting. When a maintainer applies a security patch without changing the upstream version string, the package keeps reporting its old version and a version-matching scanner keeps calling it vulnerable. A fixed statement is the only machine-readable way to correct that at scale — and the alternative, suppressing the finding in your own scanner configuration, hides the decision somewhere no downstream consumer can see it.
Where each artifact should be produced and consumed
Mapping the flow once prevents the common failure, which is generating documents nobody reads.
- At build: generate the SBOM from build context, bound to the digest. Validate it against the published schema and fail the build on a malformed document.
- At push: attach the SBOM and any exploitability statements to the image in the registry, so they travel with the artifact rather than beside it.
- At ingestion: feed statements into the scanner or vulnerability platform so statuses apply automatically, once, rather than per finding during manual triage.
- At admission: verify that the required attestations exist before a workload reaches a cluster, so a missing document is a deployment failure rather than an audit finding.
- On advisory publication: re-scan stored inventories, because a document generated last quarter can be matched against an identifier published today.
That last step is the one that repays the whole exercise, and it only works if the inventories were accurate and addressable in the first place.
What this does not solve
Being clear about the edges keeps the programme credible:
- An SBOM does not prove completeness. It records what the generator could see, which depends on the ecosystem and the tool.
- It does not establish build integrity. Provenance and signing do that, and they are separate attestations.
- It does not assess risk. Severity and exploitability come from other documents entirely.
- A statement is an assertion, not proof. Nothing verifies that a producer's claim is correct; the format makes it structured, attributable and transportable.
A consumer still has to decide whose statements it accepts and what happens when an issuer is wrong. That is a trust policy, and it needs an owner.
What to expect from a supplier
If you consume hardened images rather than building every base yourself, the supplier's automation becomes part of yours. Echo states that its images are built on controlled build infrastructure at SLSA L3, signed and attested, and delivered with SBOM, provenance and VEX (echo.ai/product); the questions worth asking any provider are whether those documents are bound to digests, regenerated on every rebuild, and published in a format your stack already parses.
Confirm the format before procurement. A mismatch there turns reconciliation into manual work that quietly never happens.
FAQs
How often should an SBOM be regenerated?
On every build that produces a new image digest, without exception. An SBOM describes one exact manifest, so a rebuilt image needs a new document even when the version number and the tag are unchanged. Teams that regenerate per release rather than per build end up with inventories that describe a manifest nobody is running, which is worse than having none.
Should we generate CycloneDX or SPDX?
Whichever your scanner, registry or customer actually accepts. For most container pipelines the practical differences are small: both record components, versions, identifiers and relationships, and both attach to an image digest. Generate one as your canonical build output and convert at the boundary where a specific consumer requires the other. Generating both independently is how two documents start disagreeing.
Can we automate VEX, or does it need human judgement?
Both. The transport is automatable — attaching statements, matching them to digests, applying them at ingestion. The judgement behind a not_affected claim is not, because somebody has to establish why the component cannot be exploited. In practice most statements a team consumes are produced by its suppliers, and the local work is deciding which issuers to trust.
Where should these documents be stored?
As registry attachments on the image, so the inventory and the artifact cannot be separated. Storing documents in an object store or an artifact repository works only while the mapping between document and digest is maintained, and that mapping is exactly what decays. If the SBOM travels with the image, a consumer who can pull the image can verify it.
Does any of this reduce our vulnerability count?
No, and expecting it to is a category error. Generating inventories and statements changes what you can see and explain, not what is installed. The reduction comes from a smaller base image, patched components and a dependency policy. What this work does is stop you re-triaging the same resolved findings every week.
Frontier models can now find and exploit zero days in your code
Find out what to do when there's no CVE, scanner alert or fix available yet.
What are the 7 blind spots in your vulnerability scans?
Discover when "0 vulnerabilities" doesn't actually mean you're clean.





.avif)
.avif)