One tells you what's in your software. The other proves how it was built.
| SBOM | SLSA | |
|---|---|---|
| Full name | Software Bill of Materials | Supply-chain Levels for Software Artifacts |
| What it is | An inventory of all components | A framework for build integrity and provenance |
| Analogy | Nutrition label on a food product | Food safety handling guidelines |
| Answers the question | What's in this software? | Was this software built securely? |
| Formats | CycloneDX, SPDX | Provenance attestations (in-toto/SLSA format) |
| Levels/tiers | No levels — you have one or you don't | 4 levels of increasing assurance |
| Tooling | Syft, Trivy, cdxgen | SLSA GitHub Generator, Sigstore, Witness |
| When it helps | Incident response — "are we affected by CVE-X?" | Tamper detection — "was our build pipeline compromised?" |
An SBOM tells you what is in an artifact. SLSA tells you whether you can trust how that artifact was produced. One is an inventory, the other is a process standard — and an accurate inventory of a compromised build is still a compromised build.
Start with SBOM, essentially always. Not because it's more important but because it's the prerequisite for answering questions, and because the effort is low: generation is a build-step plugin, and the output is immediately useful. The test of whether you need one is simple — when the next Log4Shell lands on a Friday afternoon, can you list every application and version that contains the affected package? Most organizations cannot, and that gap is what turned Log4Shell from a patching exercise into a multi-week scramble.
Move to SLSA when your threat model includes the build itself. SBOM answers "what's inside" but says nothing about whether what's inside is what the source said it should be. If an attacker compromises your CI and injects code during the build, your SBOM will faithfully describe the artifact's declared dependencies and completely miss the injected payload. SolarWinds is the canonical case: the dependency list was accurate and irrelevant.
Match the SLSA level to what you actually ship. The levels are deliberately incremental. Level 1 is provenance existing at all. Level 2 adds a hosted build service and signed provenance. Level 3 requires the build to be isolated and the provenance non-forgeable by the build itself. Higher levels cost real engineering. A team shipping an internal service has a very different justification from one publishing a package that thousands of organizations install.
Incident A — a vulnerable dependency. A critical CVE is published in a widely-used serialization library. You need to know, today, which of your 200 services include it and at what versions. With a current SBOM per artifact in a searchable store, this is a query that takes minutes, and you can tell your customers accurately which products are affected. Without one, it's an archaeology project across build files, lockfiles and container layers, and the answer you eventually produce is a guess. SBOM solved this. SLSA contributed nothing.
Incident B — a compromised build. An attacker gains access to your CI environment and modifies the build to inject a backdoor into the binary after dependency resolution. Your SBOM is generated from the manifest and is entirely accurate about your declared dependencies — and completely blind to the injected code, because the injection isn't a dependency. What detects this is provenance: a signed attestation recording which source commit, which builder and which parameters produced this artifact, verified by the consumer before deployment, so an artifact built anywhere other than your trusted builder is rejected. SLSA solved this. SBOM contributed nothing.
The two incidents are the argument for doing both, and the order — inventory first, provenance second — reflects effort more than importance.
SBOM. Two formats dominate: SPDX, which is an ISO standard and common in compliance contexts, and CycloneDX, which came from OWASP and is more oriented toward security tooling. Generate with Syft, Trivy or your build system's native plugin. The part teams underinvest in is storage and query — an SBOM generated and dropped in a build artifact directory is not an inventory, because nobody can search it during an incident. Attaching SBOMs to images in the registry and indexing them centrally is what converts the file into the capability.
SLSA. Sigstore and cosign for signing and verification, in-toto for attestation format, and GitHub Actions' or GitLab's built-in provenance generation for the common hosted cases. The crucial and frequently skipped step is verification at deploy time — generating provenance nobody checks is paperwork. An admission controller that refuses unsigned or improperly-attested images is what makes the control real.
The mature setup produces a signed SBOM as one of the attestations attached to the artifact, alongside provenance, with all of it verified before deployment. That way the inventory itself is trustworthy — an unsigned SBOM is a claim, and an attacker who can alter an artifact can usually alter a file sitting next to it. More at Supply Chain Security.
They cover different attacks: SBOM answers what's inside, provenance answers whether the build is trustworthy. Most organizations should start with SBOM because the effort is low and the incident-response value is immediate, then add provenance.
SPDX is an ISO standard and common where compliance and licensing drive the requirement. CycloneDX came from OWASP and integrates more naturally with security tooling. Either is fine; most tools convert between them, and having one consistently beats debating which.
Level 2 is a reasonable goal for most internal software — a hosted build service producing signed provenance. Level 3, with an isolated build and non-forgeable provenance, is warranted if you publish artifacts that other organizations install.
No. The injection happened during the build, so the dependency inventory was accurate and irrelevant. Build provenance with verification is the control that addresses that attack.
Only if you can query it during an incident. An SBOM written to a build directory nobody indexes provides no capability. Store them centrally, attach them to the artifacts in your registry, and make them searchable by package and version.