← All posts

What is an SBOM and why should developers care?

A Software Bill of Materials sounds like compliance paperwork. It isn't. Here's what an SBOM actually is, what CycloneDX and SPDX look like in practice, and why knowing your dependencies matters more than ever.

Modern software is mostly other people’s code. A typical web service pulls in hundreds of direct and transitive dependencies — npm packages, Go modules, Python libraries, container base images. You wrote maybe 5% of what’s running in production. The rest came from somewhere else.

An SBOM is how you keep track of all of it.

What is an SBOM?

A Software Bill of Materials is a machine-readable inventory of every component in a piece of software: the libraries it uses, the versions of those libraries, where they came from, and how they relate to each other.

Think of it like a food label — except instead of listing ingredients and nutritional values, it lists packages, versions, licenses, and checksums. And unlike a food label, it’s meant to be consumed by software, not humans.

The key word is machine-readable. An SBOM isn’t a README that says “we use React and Postgres.” It’s a structured document — JSON or XML — that a vulnerability scanner can parse, a compliance tool can validate, and a customer can ingest into their own security tooling.

Why does it matter?

In December 2021, a critical vulnerability was discovered in Log4j, a Java logging library. The CVE — Log4Shell — allowed unauthenticated remote code execution. Within 72 hours it was being actively exploited at scale.

Every security team in the world had the same urgent question: are we affected?

Teams with an SBOM answered that question in minutes. They ran a query: “does any of our software depend on log4j-core between versions 2.0 and 2.14.1?” They got a list. They started patching.

Teams without an SBOM started by figuring out what they were even running. They searched codebases, pinged developers on vacation, scraped CI logs. Some of them were still doing that a week later.

That’s the practical case for SBOMs — not regulation, not compliance theater. Just knowing what’s in your software before someone else finds out for you.

CycloneDX vs. SPDX

Two open standards dominate the space:

CycloneDX SPDX
Maintained by OWASP Linux Foundation
Current version 1.6 2.3
Formats JSON, XML, Protobuf JSON, YAML, RDF, tag-value
Primary focus Security and vulnerability management License compliance and provenance
Typical use Supply chain security, CI/CD, CVE scanning Audits, legal, open source governance

In practice, both formats cover the same core data. CycloneDX tends to be the default choice for security tooling; SPDX has deeper roots in the open source licensing world. If you’re generating SBOMs for compliance (CRA, US Executive Order 14028), produce both — the formats are not mutually exclusive and most tooling handles either.

What goes into an SBOM?

The US NTIA defined a baseline set of data fields that any SBOM should include. Both CycloneDX and SPDX cover these natively:

Field What it means
Supplier Who created or maintains the component
Component name The package or library name
Version The exact version in use
Unique identifiers purl, CPE, or a hash — something that unambiguously identifies this artifact
Dependency relationships What depends on what (direct vs. transitive)
SBOM author Who or what generated this document
Timestamp When it was generated

Dependency relationships are the field that matters most for vulnerability matching. A flat list of packages tells you what’s present. A graph tells you why it’s present — which is what you need when you’re trying to figure out whether an indirect dependency can actually be reached by an attacker.

How SBOMs are generated

You don’t write an SBOM by hand. It’s generated from the same source of truth your build system uses: the lockfile.

A lockfile — package-lock.json, go.sum, Cargo.lock, poetry.lock — is an exact, reproducible record of every dependency resolved for a build. SBOM generators read this file and translate it into CycloneDX or SPDX format, resolving package metadata (licenses, checksums, purls) along the way.

This is why SBOMs should be generated in CI, not as a one-off export. Every commit that changes a dependency changes the SBOM. If you generate it once and file it away, it’s outdated the moment someone runs bun add or go get.

Supported ecosystems vary by tool, but coverage for the major package managers — npm/pnpm/Bun, Go modules, Cargo, Poetry/pip, Maven — is broadly good today.

Who is asking for SBOMs?

Regulators. The EU Cyber Resilience Act makes SBOMs mandatory for products placed on the EU market, in machine-readable format, retained for 10 years. The US Executive Order 14028 requires federal software suppliers to provide SBOMs. These are not proposals — they’re law or enforceable policy. (More on the CRA →)

Enterprise customers. Procurement teams at larger organizations increasingly ask for SBOMs as part of vendor security assessments. It’s becoming a line item on security questionnaires alongside SOC 2 and pen test reports.

Your own security team. Or, if you’re a small team, yourself. The fastest way to know whether a new CVE affects you is to query an SBOM, not grep through repos.

Getting started

The barrier to generating SBOMs is low — the harder part is making it automatic and keeping it current.

boring.tools takes it from there: upload the SBOM from your CI with one curl call, and every component is matched against OSV and re-checked whenever new advisories appear. Every triage decision is kept per release.

The SBOM documentation lists generators for each ecosystem and the formats we accept.