Software Bills of Materials: SPDX and CycloneDX
A software bill of materials records identified components and relationships within a declared scope. State which artifact and generation method it describes, validate the chosen format version, and check identifiers and dependencies. Schema validity does not establish a complete inventory, correct licensing or the absence of vulnerabilities.
Choose a format and version supported by the consumers that will use the document. This article's fictional examples declare SPDX 2.3 JSON and CycloneDX 1.6 JSON. They demonstrate specific established versions, not a claim that those are the newest standards or that other versions are interchangeable.
TL;DR
- An SBOM records identified components and their relationships within a declared scope.
- State which artifact it describes and how it was generated, and validate it against the chosen format version (for example SPDX 2.3 or CycloneDX 1.6).
- Check identifiers and dependency references, not just schema validity.
- A valid SBOM doesn't prove a complete inventory, correct licensing, or the absence of vulnerabilities.
- Pick a format and version your consumers support; versions aren't interchangeable.
Quick Example
This Python creates two inventories from the same two fictional component declarations. It extracts nothing from a real package, build or deployment. The companion checker validated the resulting JSON against the recorded official versioned schemas and added local identifier/reference checks.
Both examples validate against their declared JSON schemas, and missing required fields, duplicate local identifiers, and dangling references should be rejected by the schema or a reference check. Validation does not establish full specification semantics, artifact completeness, license conclusions, advisory matching or exploitability. NOASSERTION preserves the absence of a license determination.
Core Concepts
Scope and provenance make an inventory interpretable
Identify whether the document describes source dependencies, a resolved build, an image, a distributed binary or a deployed environment. Those views can differ. Record artifact identity, generation tool/version, configuration, date and important exclusions so a consumer knows what the inventory can support.
Do not assume a lockfile describes every shipped component. Native libraries, bundled assets, generated code, system packages and runtime-delivered components can fall outside one extraction method. Conversely, development dependencies may appear in source inventory without being shipped. Verify the boundary relevant to the consuming workflow.
Components and relationships are separate evidence
SPDX's document/package sections define document identity and package references, while its relationship section distinguishes links such as DESCRIBES and DEPENDS_ON. The published 2.3.1 explanatory specification retains the SPDX-2.3 version field used here. SPDX document fields, relationships
CycloneDX describes component dependency relationships, including direct and transitive structure. Its ability to express additional information does not mean every generator discovers or populates it. CycloneDX overview
The fixture deliberately supplies one dependency edge. It demonstrates representation only. A list of components without verified relationships may still be useful, but the consumer should not silently interpret missing edges as proof that no dependency exists.
This is an editorial workflow map. Only the fictional generation, schema validation and local reference cases were executed.
Schema validation and semantic validation differ
The official SPDX 2.3 and CycloneDX 1.6 JSON schemas describe machine-checkable structure for those representations. The local checker uses the downloaded schema snapshots and records their hashes. SPDX schema, CycloneDX schema
Also check document-local uniqueness, relationship endpoints, required policy metadata and specification rules that a JSON validator may not fully express. A document can parse and pass a schema while describing the wrong artifact or omitting an important component. A schema pass is a bounded technical result, not full compliance certification.
Inventory becomes input to vulnerability work
OSV's query API illustrates correlating a package and version or other supported identity with known vulnerability records. Accurate ecosystem and version identity matter to that match. No advisory query was made for the fictional components. OSV query API
Treat matches as findings to triage with evidence about the actual artifact, affected code and environment. An unmatched component is not proof of safety: identification can be incomplete, the advisory database can lack a record, and previously unknown issues remain possible. Likewise, a match does not by itself determine exploitability in every deployment.
Best Practices
Generate inventory at a reproducible boundary appropriate to the consumer, and preserve the artifact identity with the SBOM. Regenerate when the artifact or generation assumptions change. A reused filename without provenance can leave a vulnerability workflow assessing yesterday's build.
Validate with tools and schemas for the declared version, then perform meaningful semantic and coverage review. Keep the actual tool result separate from broader publisher or customer requirements. Do not relabel one format version as another without a supported conversion and review of lost information.
Test malformed and ambiguous documents: missing fields, duplicated identifiers, unresolved relationships, unknown versions and incomplete package identity. The supplied checker covers selected required-field and local-reference cases, not every rule or generator behavior.
Preserve uncertainty instead of inventing license or component evidence. A license expression, download location, supplier or vulnerability status should come from a defensible source. Actual licensing conclusions may require qualified review; the example deliberately makes none.
Integrate findings with ownership, prioritization, remediation and verification. Keep the installed/shipped version and the corrected artifact connected to the ticket. A successful scanner run without an accountable response process can create an inventory of unresolved work rather than a safer release.
Reverse an inventory-complete conclusion when artifact inspection finds components outside the generator's declared scope. Add an appropriate collection method or narrow the claim. The useful SBOM is the one whose boundaries a consumer can understand and challenge.
Common Mistakes
Treating schema validity as complete discovery
Treating package names as unique identities
Reading no findings as no vulnerabilities
Claiming full conformance from selected checks
FAQ
How do I validate an SBOM?
Validate it against the JSON schema for its declared format version, check that every reference resolves and identifiers are unique, and confirm it describes the artifact you actually ship. Schema validity says nothing about completeness, license conclusions, or vulnerabilities.
Why use SPDX 2.3 and CycloneDX 1.6?
They are explicit example contracts with official schemas. The article makes no newest-version claim. Choose versions supported by the actual producer and consumer requirements.
Does an SBOM prove software is vulnerability-free?
No. It supports inventory and correlation within its scope. Coverage, identity, advisory knowledge, applicability and remediation still need evidence and ownership.