What Is a Software Bill of Materials (SBOM)? A Beginner's Explainer

Ask five developers what is inside the application they shipped last week and you will get five confident answers, each a little different. That is not sloppiness. A modern service is assembled from hundreds of open source packages, each dragging in its own dependencies, and no human holds the whole picture in their head. A Software Bill of Materials is an attempt to write that picture down in a form a machine can read.

The idea is old — manufacturers have shipped bills of materials for physical products for a century — but it arrived in software with unusual force, pushed by regulation, procurement contracts and one very bad December.

What an SBOM Actually Is

An SBOM is a structured list of the components that make up a piece of software, together with the metadata needed to identify each one unambiguously. Think of the ingredients panel on a food packet, but for a container image, a binary or a repository.

It is worth being precise about what an SBOM is not. It is not a vulnerability report. It is not the output of a security scanner. It does not tell you whether your code is safe, and it does not mean you are compliant with anything. It is raw material: an inventory you can query when a question arrives. The analysis happens on top of it.

That distinction matters, because teams often expect an SBOM to solve a problem it was never designed for. A good SBOM answers "what is in here?" quickly and reliably. Everything else follows from that.

The Minimum Ingredients

An inventory is only useful if the entries are consistent. In the United States, the National Telecommunications and Information Administration published a set of minimum elements that most tools and buyers now treat as the floor:

  • Supplier name — who produced the component, not who shipped it to you.
  • Component name — the package or library identifier.
  • Version — the exact release, not a range.
  • Other unique identifiers — usually a package URL such as pkg:npm/lodash@4.17.21, or a CPE for older naming conventions.
  • Dependency relationship — which component pulls in which, so you can trace a transitive dependency back to something you chose.
  • Author of the SBOM data — the tool or team that produced the file.
  • Timestamp — when the inventory was generated, because it goes stale the moment a dependency changes.

Treat that list as a starting point rather than a target. Hashes, licences, and build provenance are worth adding when your tooling supports them. Hashes in particular let you confirm that the component you inventoried is the one you actually deployed.

Two Formats Cover Most of the Ground

You will encounter dozens of formats, but two dominate.

SPDX

Maintained by the Linux Foundation and standardised as ISO/IEC 5962, SPDX grew out of licence compliance work. It is strong on licensing detail and can be serialised as tag-value text, JSON, YAML or RDF. If your legal team cares about obligations attached to copyleft dependencies, SPDX tends to give them more to work with.

CycloneDX

An OWASP project, later standardised through ECMA, CycloneDX was designed with security use cases first. It carries vulnerability and VEX information natively, which makes it convenient when you want to say "we checked, and this component is not affected by that advisory."

Both are widely supported. Pick one, document the choice, and move on — the format argument is far less important than whether you generate anything at all.

Why Governments and Enterprises Now Require Them

The turning point was a software supply chain executive order signed in the United States in 2021, which pushed federal agencies toward requiring SBOMs from their software suppliers. Around the same time, the European Union began shaping the Cyber Resilience Act, which brings SBOM expectations into the product security requirements for hardware and software sold in the EU. Different jurisdictions, different timelines, similar direction.

The technical trigger was sharper. When the Log4j vulnerability landed in late 2021, the hard part for most organisations was not patching — it was finding out where Log4j had ended up. Teams resorted to grepping across repositories and asking vendors to confirm by email. An accurate SBOM turns that scramble into a database query.

Commercial pressure followed. Enterprise buyers now write SBOM delivery into contracts. Investors ask for supply chain visibility during due diligence. Regulated sectors ask for it in audits. Note that obligations vary by jurisdiction, contract and sector, so if you are making compliance claims, have legal counsel review them rather than relying on a blog post.

How to Generate One

Generation is mostly a solved problem, provided you scope it sensibly and run it in the right place.

  1. Choose a scope. Generate per artifact — one container image, one release binary, one repository — rather than trying to inventory an entire organisation in a single pass.
  2. Pick a generator that understands the ecosystem. Syft and Trivy handle container images and filesystems well. Language-native plugins often do better on application dependencies: CycloneDX plugins for Maven and Gradle, npm sbom for Node projects, cyclonedx-bom for Python, and CycloneDX tooling for Go modules.
  3. Resolve dependencies properly. Tools that only parse a manifest frequently miss transitive packages. Prefer generators that read lockfiles or inspect the built artifact, since that reflects what actually ships.
  4. Run it in CI. A laptop run is a demonstration; a pipeline step is a process. Generate on every build of a release candidate.
  5. Store it with the artifact. Attach the SBOM to the release, the image registry, or your artifact repository, alongside the build it describes.

Do a sanity check on the output before trusting it. Compare the component count against what you expect, and confirm that a dependency you know you use appears. Generators differ in completeness, and a sparse SBOM is worse than none because it creates false confidence.

Making an SBOM Useful After You Generate It

A file sitting in a repository changes nothing. Three workflows earn their keep. First, vulnerability triage: feed the SBOM into a scanner that matches components against advisory databases, so new CVEs surface against systems you already run. Second, incident response: when the next widely exploited library appears, answer "are we affected, and where?" in minutes. Third, licence and policy checks, where you verify that a new dependency does not conflict with how you distribute your product.

VEX documents are the natural companion here. An SBOM tells you a vulnerable component is present; VEX lets you record that it is present but not exploitable in your configuration, which saves everyone from re-litigating the same false positive every quarter.

Start Small, Automate Early

Pick one service. Generate an SBOM for its container image in CI, store the file next to the image, and run one scan against it. Then write down two decisions: which format you standardise on, and how you identify components — package URLs are the pragmatic default. Add a retention rule so you keep an SBOM for every release you still support.

Do that for a month and you will have something more valuable than a policy document: a repeatable habit that answers real questions during real incidents. The organisations that handle supply chain surprises well are rarely the ones with the most elaborate programme. They are the ones that started early, kept it boring, and never let the inventory drift too far from what they actually ship.

Photo: RDNE Stock project / Pexels

You Might Also Like