Skip to main content

Canonical SBOM format

Workflows does not process SPDX and CycloneDX directly. Everything entering the platform is converted into one internal representation — the canonical SBOM format — and every processing node works on that.

You do not have to author this format. Readers produce it and writers consume it. It is documented because knowing its shape explains what the nodes are actually doing to your data, and what survives a conversion.

Why it exists

SPDX and CycloneDX model the same domain differently: different field names, different structures, different ideas of what a component is. Supporting both throughout the pipeline would mean every node handling every format.

Instead, conversion happens once at the edges. In between, there is one model, which means:

  • Nodes are simpler and behave identically regardless of the input format.
  • A workflow can read one format and write another.
  • New formats can be added by writing a reader and a writer, without touching anything in the middle.

The canonical format is designed as a superset of SPDX and CycloneDX, so it can hold everything meaningful from either without discarding it.

Structure

A canonical SBOM is a single JSON document:

Document
├── id, namespace, format, type
├── name, version, created
├── creators[] people, organizations, or tools that produced the SBOM
├── license, licenseNamespace
├── references[], comment

├── elements[] packages, files, snippets, tools, services …
├── relationships[] directed links between elements
├── annotations[] notes, warnings, errors, policy violations, reviews
├── customLicenses[] non-standard license texts
└── vulnerabilities[] vulnerability records

Three ideas carry most of the weight.

Elements

One array holds every kind of entity — packages, files, snippets, tools, applications, services, frameworks. They share one shape, and a type field says which kind each is.

Each element can carry a name and version, supplier and originator, checksums, identifiers (purl, cpe, swid), licensing information (concluded, declared, and derived from files), and arbitrary properties.

Element typeWhat it is
PACKAGEA software package or library.
FILEAn individual file.
SNIPPETA portion of a file.
DOCUMENTA reference to another SBOM.
TOOLA tool used in creating or analyzing the SBOM.
APPLICATIONAn application component.
SERVICEA service component.
FRAMEWORKA framework component.
OTHERAnything else.

Relationships

One array holds every association between elements, as explicit directed links: from, to, and a type.

Where CycloneDX nests components inside one another, the canonical format flattens that into CONTAINS relationships. The result is a graph rather than a tree, which is easier to process and can express structures that nesting cannot.

Common relationship types include DEPENDS_ON, BUILD_DEPENDENCY, DEV_DEPENDENCY, TEST_DEPENDENCY, CONTAINS and CONTAINED_BY, DESCRIBES, GENERATES and GENERATED_FROM, STATIC_LINK and DYNAMIC_LINK, and COPY_OF and VARIANT. The full vocabulary unifies the SPDX and CycloneDX relationship sets.

Annotations

One array holds every note attached to the document, an element, or a relationship. This is how nodes record what they found and what they did.

Annotation typeUsed for
ERRORA problem found during processing — including a mandatory regulatory element that is missing.
WARNINGA potential issue, such as a recommended element that is absent or a conflict during a merge.
POLICY_VIOLATIONA policy rule that was broken.
REVIEWA review note.
NOTEA general note — how normalization changed a field, for example.
COMMENTA general comment.
OTHERAnything else.

Annotations are what Generate PDF Report turns into a document, and its parameters map directly onto these types.

Document types

The type field describes what the SBOM is of: SOURCE, BUILD, ANALYZED, DEPLOYED, RUNTIME, DESIGN, DISCOVERY, DECOMMISSION, or OTHER.

Required fields

A canonical document must have id, format, name, version, created, elements, and relationships. Everything else is optional.

Undeclared fields are not permitted anywhere in the document. That strictness is deliberate: it keeps data consistent across every node rather than letting format-specific debris accumulate.