SBOM
SBOM best practices
Most SBOM programs produce files. The good ones produce answers: what is in this release, are we affected, and who fixes it. These ten practices are what separate the two.
Updated
Generating SBOMs
1. Generate in CI, for every release
An SBOM made by hand goes stale before anyone reads it. Make it a step in the pipeline that builds the release, or use a runner that produces one without a step at all, so that no release ships without it. For GitHub Actions, see how to generate an SBOM in GitHub Actions.
2. Describe the build that shipped
Builds are not reproducible by default. Building the same commit twice gives no guarantee of the same dependencies, because versions resolve at build time and steps can vary. An SBOM from a laptop or a later scan describes a similar build, not the one you shipped. Only an SBOM from the CI build that produced the release proves what is in it. See build-time SBOMs.
3. Cover more than the lockfile
A lockfile is not a record of what shipped. Install scripts download code, Rust build scripts fetch files, and container builds bring in a base image with its own operating system packages. Decide what the SBOM must cover, then test it: search your SBOM for a package from your base image and a build tool.
4. Include transitive dependencies and relationships
Vulnerabilities usually sit below your direct dependencies. A flat list shows that a component is there, but not what to upgrade. Keep the dependency graph in the SBOM, so a finding comes with the package that pulls it in.
5. State what you could not see
The 2026 Minimum Elements ask SBOM authors to identify unknown information explicitly. A partial SBOM that says so is worth more than a partial SBOM that looks finished. Record the tool, its version and the generation context too, so a reader can judge what the file covers.
Keeping SBOMs
6. Keep one SBOM per release, tied to the artifact
When a customer on an old version asks if they are exposed, you need that version's SBOM rather than the latest one. Store each SBOM with the build and the artifact it describes, and decide how long to keep it based on how long you support the release. Hashes in the SBOM help you tie it to the exact artifact.
7. Pick a format and an identifier, and stick to them
Standardize on CycloneDX or SPDX, a format version and package URLs as identifiers. Most of the pain in comparing SBOMs comes from tools naming the same thing differently. Validate each file in the pipeline, and ask suppliers for the same format.
Using SBOMs
8. Monitor what shipped, not only what you are building
The most valuable moment for an SBOM is the day after an advisory lands for software released last year. A scan in a pull request cannot help then. Re-evaluate the stored SBOMs of supported releases against new vulnerability data, so that a new advisory turns into a list of affected releases.
9. Route findings to an owner, and record the decision
An SBOM with a thousand matched vulnerabilities is a list, not a plan. Rank findings with a prioritization method, send each to the team that owns the fix, and record why you did not act on the rest, for example in a VEX statement.
10. Use the same SBOM for customers and auditors
Customers, auditors and regulators ask similar questions. Answer them from the SBOM your own teams use, rather than producing a separate document that drifts. If you share SBOMs, decide who may see them and how they get updates, and ask your suppliers for the same.
Common mistakes
| Mistake | Why it hurts | Instead |
|---|---|---|
| One SBOM per repository | It says nothing about any specific release | One per release, tied to the artifact |
| Generating only at audit time | It describes a build nobody shipped | Every release, in CI |
| Treating the SBOM as finished | New advisories arrive after release | Keep monitoring it |
| Comparing only the component count | More is not better if the entries are wrong | Check specific packages you know are there |
How CRACI handles this
CRACI covers the practices that depend on the build. It is a GitHub Actions runner that records every package each job fetches, including hidden dependencies that no lockfile lists, into a CycloneDX or SPDX SBOM with a completeness state. It keeps every past build and its SBOM within your plan's retention, re-evaluates monitored SBOMs as new vulnerabilities appear, and shows which builds contained a vulnerable dependency. Security teams triage findings and send them to the teams that own the fix. See SBOM management for how managers compare, or the best SBOM tools.
SBOM best practices: frequently asked questions
When should you generate an SBOM?
During the CI build that produces the release, every time. An SBOM made at that point describes what shipped, while one made later describes a rebuild or a scan.
How long should you keep SBOMs?
At least as long as you support the release, plus whatever your regulators or contracts require. You need the SBOM of an old version to tell whether its users are affected by a new vulnerability.
Should SBOMs be automated?
Yes. A manual SBOM is out of date by the next release. Generate SBOMs in the pipeline, validate them there, and store them with the build.
Should you share your SBOM with customers?
Share it when a customer or regulator asks, under terms you are comfortable with. An SBOM reveals what you use, so many companies share it on request rather than publish it.
What is the difference between an SBOM and SBOM management?
An SBOM is one file. SBOM management is the ongoing work of storing SBOMs by release, monitoring them for new vulnerabilities and making them available to the people who need them.
Get an SBOM from every build
Point one GitHub Actions workflow at CRACI and see a recorded SBOM, with its completeness state, for the build you ship.
Book a demo