sbom security basics

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.

boring.tools team

boring.tools team

The team behind boring.tools.

4 min read
What is an SBOM and why should developers care?

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:

CycloneDXSPDX
Maintained byOWASPLinux Foundation
Current version1.62.3
FormatsJSON, XML, ProtobufJSON, YAML, RDF, tag-value
Primary focusSecurity and vulnerability managementLicense compliance and provenance
Typical useSupply chain security, CI/CD, CVE scanningAudits, 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:

FieldWhat it means
SupplierWho created or maintains the component
Component nameThe package or library name
VersionThe exact version in use
Unique identifierspurl, CPE, or a hash — something that unambiguously identifies this artifact
Dependency relationshipsWhat depends on what (direct vs. transitive)
SBOM authorWho or what generated this document
TimestampWhen 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 generates CycloneDX and SPDX SBOMs directly from your repositories on every commit, scans them against OSV, NVD, and GitHub Security Advisories, and keeps a versioned history so you can see exactly what was in any release. No CI pipeline changes required — connect a repository and it handles the rest.

If you want to understand the generation side in more detail, the SBOM documentation covers the supported ecosystems, output formats, and how to trigger scans manually or via the CLI.