Blog Orchestrating multiple SBOMs 17 min
DevOpsSecurity

Orchestrating multiple SBOMs

SparkFabrik Team17 min read
Orchestrating multiple SBOMs
Listen to this article
TL;DR
A product with twelve services easily churns out thirty SBOMs per release, but the Cyber Resilience Act requires just one: that of the product placed on the market. Generating them is no longer the issue; combining them into an authoritative, signed document retained for ten years is. We look at when it makes sense to merge everything into a single file and when, instead, a root BOM referencing components without flattening them is needed, with the decisive test: how much time passes from a CVE to the list of impacted services.

A product composed of twelve services, three different base images, and two vendor-purchased components easily produces twenty or thirty SBOM documents for each release. The Cyber Resilience Act1, however, asks for one: the unit of evidence is the product placed on the market, not the repository nor the single build.

It is the gap between how pipelines work and how the regulator thinks. SBOM generation is a solved problem: Syft2, Trivy3, and registry-integrated scanners produce CycloneDX or SPDX in a few seconds. What is missing, in most setups we have seen, is composition: an authoritative document per product version that holds together component SBOMs without flattening them into a monolithic file. This article addresses that problem: how to link, sign, and maintain over time a product bill of materials in multi-service architectures.

Why do SBOMs multiply in a multi-service product?

Multiplication is not a configuration flaw: it is a structural property of cloud-native architectures. It operates along three axes that combine by multiplication, not addition:

Three-dimensional expansion of SBOMs

  1. Services and repositories: each service with its own release cycle generates its own documents, and each monorepo with multiple publishable artifacts behaves as N distinct sources.
  2. Type along the lifecycle: CISA taxonomy4 distinguishes Design, Source, Build, Analyzed, Deployed, and Runtime SBOMs. These are different views of the same software, not copies.
  3. Origin of components: first-party code, base images with their OS packages, language runtimes, firmware, third-party components delivered by vendors.

A Source SBOM and a Build SBOM for the same service are not redundant. The former describes what is declared in manifests and lock-files; the latter describes what actually entered the shipped artifact. Generating only from source yields both false positives (declared dependencies that are never compiled) and blind spots: system libraries in the base image, static binaries linked during build, vendorized modules. The first case inflates triage, while the second makes it incomplete right where risk is most opaque.

The recurring failure mode has a recognizable shape. Folders of CI artifacts with limited retention, a spreadsheet tracking which merge is the most recent, no document that anyone is willing to declare authoritative for the release on the market. This SBOM sprawl carries a cost that manifests at the exact worst moment: upon the appearance of an actively exploited vulnerability, the team does not answer the question “which product version contains the affected component and in which service”, but the much poorer question “where is the right file”.

The probability of that question arising is not remote. The 2024 OSSRA report shows 91% of examined repositories containing components that are ten versions or more behind5: in a product with ten services, the presence of at least one outdated and potentially affected component is the normal condition, not the exception. Granular visibility into dependencies is the prerequisite for everything else, a point we already covered when analyzing how the Software Bill of Materials makes third-party risks traceable under the CRA.

Technically, the regulation asks for four things, and it is best to read them as specifications. The SBOM must be machine-readable: JSON or XML in CycloneDX or SPDX format6, whereas a PDF attached to documentation does not satisfy the obligation. The common format is not prescribed. The legal minimum, set by Annex I, Part II of the CRA, is first-level dependencies, but in cloud native, transitive dependencies are the core of the risk, making the legal minimum a floor, not a goal. Above all: a representation of dependency and containment relationships is required, not a flat list of names.

The SBOM is part of the technical documentation defined in Annex VII of the CRA1: it is not proactively transmitted, but must exist when placed on the market and be producible upon reasoned request from a market surveillance authority. Deadlines set the context: September 11, 2026 for vulnerability reporting obligations, December 11, 2027 for full application.

CYBER RESILIENCE ACT   Are you ready for the new security requirements? Integrate security-by-design across your entire digital product lifecycle. Achieve full compliance and turn a regulatory obligation into a competitive advantage.  

Compose or merge: which strategy holds up in a product audit?

Both approaches are compliant. The CRA does not impose an aggregation mechanism; it mandates the existence of a machine-readable document representing the product with its dependency relationships. The choice between merging and linking is therefore an engineering decision, and must be justified by the informational costs it entails.

Architectural comparison: Flat Merge vs Hierarchical Compose

What you lose when you merge everything into one file

Flat merge has a paradox at its core: deduplication. In build tools, eliminating duplicates is good practice; in supply chain analysis, deduplicating components from N documents erases the only necessary information: which service uses which version. Names remain, the map disappears.

  • Triage changes nature: from a query on the graph (“which components of product 3.4 depend on libX < 2.9, and in which service?”) to a text search followed by manual verification service by service. This is where MTTR expands, not in writing the patch.

  • Lifecycles are decoupled: a merged document is a snapshot that ages upon the first independent deployment of a single service, and every regeneration requires rebuilding the entire file.

  • Provenance is lost: hashes and signatures of original documents do not survive merging, so integrity is verifiable only on the aggregate.

Merging remains the correct choice under precise conditions: a substantially monolithic product, a few dozen components, a single release cadence, or an SBOM consumer that cannot resolve external references. In those cases, it produces an autonomous, verifiable artifact with less surrounding infrastructure.

Hierarchical compose: a root BOM that references, not copies

The structure is simple: one product document per version, whose application-type components represent services, each with an external reference to its own SBOM. In CycloneDX, the mechanism is the externalReference of type bom carrying a BOM-Link7 in the form urn:cdx:<serialNumber>/<version>, capable of pointing to an entire document or to a single bom-ref within it. In SPDX, the equivalent is achieved using the ExternalDocumentRef pair plus Relationship (DESCRIBES, CONTAINS, DEPENDS_ON).

The resulting properties are those that merging cannot offer: independent regeneration per service, integrity verifiable document by document with separate checksums and signatures, preserved provenance, and manageable file sizes even with hundreds of components per service. It follows the same logic as the hierarchical assembly of a manufacturing bill of materials, where the product level references sub-assemblies instead of listing every single screw.

The constraint, which must be declared: reference resolution is the consumer’s responsibility. If the root BOM points to unresolvable URNs or expired artifacts in a registry with a thirty-day retention policy, the evidence breaks and the document becomes an unfulfilled promise. Composition therefore requires immutable, addressable storage for component SBOMs, with the same retention as the product. Evaluating this type of architectural trade-off, where a format choice becomes an infrastructure requirement, is territory we systematized in our guide to defense models for cloud-native architectures.

SUPPLY CHAIN SECURITY   Protect every stage of your software lifecycle And turn security into a competitive advantage.  

The diagram: how to read a root BOM

flowchart LR P["Product SBOM v3.4
CycloneDX 1.6
metadata.component: application"] S1["api-gateway"] S2["checkout-service"] S3["frontend"] O1["OCI image SBOM
OS packages and runtime"] O2["OCI image SBOM
OS packages and runtime"] O3["OCI image SBOM
OS packages and runtime"] F["Vendor SBOM
reconciled"] V["Product VEX v3.4"] P -->|"externalReference type=bom (BOM-Link)"| S1 P -->|"externalReference type=bom (BOM-Link)"| S2 P -->|"externalReference type=bom (BOM-Link)"| S3 S1 -->|CONTAINS| O1 S2 -->|CONTAINS| O2 S3 -->|CONTAINS| O3 F -.->|"reconciled input, not direct link"| P P --> V

The edges carry references, not copied content: the root BOM remains the sole authoritative document for the release, and each leaf retains its own signature. The side node is the least obvious point: the vendor SBOM does not enter as an opaque link to a third-party URL, because in that case evidence would depend on the availability of an endpoint we do not control. It must be reconciled first, as explained below.

How do you build the product SBOM inside the pipeline?

Every choice here must be anchored to a requirement: it is generated from the artifact because evidence must reflect what was shipped, identifiers are normalized because component tracking demands it, and it is signed because the integrity of preserved evidence is part of the technical documentation.

Generate from the built artifact, not from source

Operational rule: the Build SBOM is generated from the OCI image or binary produced by the pipeline, and compared with lock-files and source code to detect discrepancies. Where tooling cannot infer (such as static binaries, firmware, or vendorized dependencies), manual records that are tracked and dated are added.

# syft 1.x, trivy 0.5x - use digest, not tag
IMAGE="registry.example.com/checkout-service@sha256:9f2a...c41d"
DIGEST="9f2a...c41d"

# primary generator: CycloneDX JSON output to versioned file per service and digest
syft "$IMAGE" -o cyclonedx-json="sbom/checkout-service-${DIGEST}.cdx.json"

# second scanner on the same artifact, to compare component sets
trivy image --format cyclonedx \
  --output "sbom/checkout-service-${DIGEST}.trivy.cdx.json" "$IMAGE"

Honest note: two generators on the same artifact do not produce identical sets. Syft and Trivy typically diverge on statically compiled binaries and packages installed outside package managers. The delta is not a bug; it is information about analyzer coverage. It should be recorded alongside the SBOM, and certainly not hidden by choosing the tool that returns fewer lines.

Normalize component identity before composing

Composition only works if a component is consistently identifiable across documents generated by different tools at different times. The minimum fields, consistent with CISA minimum elements8 and BSI TR-03183 technical guidelines9, are:

  • component name and exact version;

  • vendor or author;

  • Package URL (purl)10, or CPE11 where purl is not applicable;

  • artifact hash (SHA-256);

  • relationship with the parent component.

The problem is concrete: the same package appears as openssl among OS packages, as libssl3 with the distribution name, and as an embedded dependency of a Go binary. Without a normalized purl, a product triage query returns three distinct entities, making the response to authorities or customers incomplete despite being formally produced. Normalization must be executed in the pipeline as a deterministic, versioned step, never manually during an audit.

Assemble, sign, publish

The product release job constructs the root BOM with metadata.component set to the product and version, application components for each service, and external references to already published SBOMs.

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.6",
  "serialNumber": "urn:uuid:8f7c1c1e-6a3e-4c0b-9e1a-2d5b7f0a11c4",
  "version": 1,
  "metadata": {
    "component": {
      "bom-ref": "prod-retail-3.4.0",
      "type": "application",
      "name": "retail-platform",
      "version": "3.4.0"
    }
  },
  "components": [
    {
      "bom-ref": "svc-checkout-2.11.3",
      "type": "application",
      "name": "checkout-service",
      "version": "2.11.3",
      "externalReferences": [
        {
          "type": "bom",
          "url": "urn:cdx:3e671687-395b-41f5-a30f-a58921a69b79/1"
        }
      ]
    }
  ],
  "dependencies": [
    { "ref": "prod-retail-3.4.0", "dependsOn": ["svc-checkout-2.11.3"] },
    { "ref": "svc-checkout-2.11.3", "dependsOn": [] }
  ]
}

When the consumer cannot resolve references, the alternative path is a hierarchical merge, which at least preserves component nesting:

# cyclonedx-cli 0.32.x - hierarchical merge, preserves assembly structure.
# Merges only canonical, normalized SBOMs from product services.
# One per service: not the raw glob, which would include both Syft
# and Trivy outputs for the same artifact.
cyclonedx merge --hierarchical \
  --input-files \
    sbom/canonical/api-gateway.cdx.json \
    sbom/canonical/checkout-service.cdx.json \
    sbom/canonical/frontend.cdx.json \
  --name retail-platform --version 3.4.0 \
  --output-file product-3.4.0.cdx.json

# cosign 2.x - keyless signing via OIDC, verifiable bundle alongside the document
cosign sign-blob --yes product-3.4.0.cdx.json \
  --bundle product-3.4.0.cdx.json.bundle

Automating these steps within CI/CD, with scanning and signing (for example via Cosign12) as native steps rather than optional jobs, is the part of DevSecOps work that we described when discussing tooling and pipeline integration in the cloud. The signed SBOM then goes into immutable storage, and the reference to the file enters the technical documentation of the release along with the tool name, version, and generation date.

flowchart TD A["Service pipeline
OCI image build"] --> B["Syft + Trivy
Build SBOM per digest"] B --> C["Purl normalization
deterministic step"] C --> D["Immutable SBOM store
addressable by URN"] D --> E["Product release job
root BOM assembly"] E --> F["Cosign: keyless signing"] F --> G["Technical documentation
10-year retention"] D --> H["Graph ingestion
GUAC: triage query"]

Vendor SBOMs, missing information, and evidence lifecycle

Two failure modes remain open even in well-automated setups: documents arriving from third parties and maintaining evidence over time.

Reconciliation of third-party SBOMs and &lsquo;Known Unknowns&rsquo; management

Vendor SBOMs are inputs, not the finished artifact

The scenario is recurring. One vendor delivers CycloneDX, a second SPDX, a third a PDF with a list of libraries; the release folder contains three links to three different portals. That is vendor material, not a product record, and in the event of a reasoned request, it fails to answer which version of our product contains the affected component.

Reconciliation follows a precise sequence:

  1. convert or normalize identity fields (purl, version, hash) into the internally used schema;
  2. integrate components into the product bill of materials, or link them via BOM-Link after verifying that the reference is resolvable and persistent;
  3. retain original upstream documents as supporting evidence, noting receipt date and channel;
  4. explicitly record what could not be determined.

The fourth point distinguishes defensible documentation from deficient documentation. When a vendor fails to deliver a complete SBOM, the component is not omitted: known unknowns are documented, namely contractual and purchasing evidence, verifiable fields gathered independently by scanning received binaries, hashes and version proof, plus an explicit note on what cannot be determined. A declared absence is evidence; a silent absence is non-compliance.

The implications of this chain of responsibility regarding third-party components and upstream dependencies represent a topic that European regulation shifted from the community onto those who place products on the market, and reconciliation is where that responsibility becomes operational.

How often to regenerate and how long to retain

Regeneration responds to triggers, not a calendar: changes in software or firmware versions, patch releases, changes in vulnerability exploitability status resulting in a VEX (Vulnerability Exploitability eXchange) update, additions, removals, or replacements of components, significant design modifications, or changes in applied standards. Periodic schedules remain useful as a safety net: quarterly reviews of SBOMs and vulnerability status, annual reviews of technical documentation, and a freeze before the end of the support period.

Here composition shows its strongest argument. Triggers are local to the service, so a single document is regenerated and the root BOM is reissued upon product release; in merging, every local trigger requires rebuilding the entire document, risking unwanted deltas on components nobody touched.

Regarding retention, the obligation is long-term, mandated by Article 13 of the CRA1: at least ten years from placement on the market, or the entire support period if longer, starting from the last unit placed. This excludes CI as a storage location.

For example, if the registry is Google Artifact Registry13, the reference service for software composition is Artifact Analysis, which supports SBOM generation and management for archived artifacts alongside vulnerability scanning14: a solid starting point, but not a compliance archive. Repository default retention and cleanup policies do not align with a ten-year obligation, and must be configured or supplemented with dedicated storage.

To manage this complexity long term, infrastructure must evolve beyond simple file saving. It is worth evaluating specific tooling for document fetching, storage, and transformation, such as Bomctl15, alongside a graph query layer like GUAC16 to answer triage queries in a timely manner.

Final point, often overlooked: the SBOM is confidential technical documentation, not public material. It is a component map useful to anyone seeking an entry point. Release to market surveillance authorities occurs upon reasoned request (in Italy, the reference role belongs to ACN), and to business customers under NDA, tracking who received which version and when. International convergence on these principles is documented in the joint guidance A Shared Vision of Software Bill of Materials for Cybersecurity17 published in September 2025 by CISA, NSA, and nineteen partners.

Operational lessons

The decision rule fits in two lines: if the product has more than one independent release cycle, hierarchical compose is the only maintainable strategy; below that threshold, merging costs less and easily passes an audit.

Three things we would do differently, based on our experience with multi-service pipelines:

  1. Treat component SBOM storage as a long-term artifact from day one, not as CI output with default retention. Recovering expired documents after six months means regenerating them from images that no longer exist.
  2. Normalize identifiers in the pipeline before volume makes the operation retroactive. At three hundred documents, retroactive normalization becomes a project, not a step.
  3. Measure orchestration quality with a single, timed question: how long does it take, starting from a CVE, to list affected product versions and impacted services? If the answer is measured in hours, the evidence architecture is failing, regardless of formal document compliance.

One issue remains open and must be stated: consumer maturity in resolving BOM-Links is still uneven, making this the strongest argument against pure composition today. A defensible strategy maintains the linked root BOM as the authoritative source while being able to produce a flattened view on demand as a derived export, never as the reference document.

The next and final article in the series covers observability (logs, metrics, and traces) as the technical foundation for meeting notification and reporting obligations under CRA and NIS2.

We work on these topics daily in our software supply chain security practice, and as members of OpenSSF18, CNCF, and LF Europe, we contribute to defining tools that make this evidence verifiable rather than merely declared.

Need a discussion, an audit, or dedicated consulting on security, DevSecOps, or CRA compliance? Contact our experts.

SUPPLY CHAIN SECURITY   Protect every stage of your software lifecycle And turn security into a competitive advantage.  

Notes and sources


  1. Cyber Resilience Act, The Cyber Resilience Act (Regulation (EU) 2024/2847) is an EU law mandating cybersecurity requirements, including machine-readable SBOMs and 10-year documentation retention, for digital products. (source: http://data.europa.eu/eli/reg/2024/2847/oj↩︎ ↩︎ ↩︎

  2. Syft, Syft is an open-source CLI tool and Go library developed by Anchore for generating Software Bill of Materials (SBOMs) from container images and filesystems. (source: https://github.com/anchore/syft↩︎

  3. Trivy, Trivy is an open-source vulnerability and misconfiguration scanner by Aqua Security. It scans containers, filesystems, and repositories, and can generate SBOMs in formats like CycloneDX. (source: https://trivy.dev/↩︎

  4. CISA, The Cybersecurity and Infrastructure Security Agency (CISA) is the U.S. cyber defense agency that publishes official guidance on the Minimum Elements for a Software Bill of Materials (SBOM). (source: https://www.cisa.gov/news-events/news/cisa-and-partners-unveil-updated-software-bill-materials-resource-improves-transparency-security-and↩︎

  5. According to the 2024 OSSRA report (Open Source Security and Risk Analysis), 91% of examined code repositories include components that are 10 versions or more behind. (source: SBOM: la chiave per la sicurezza software nella supply chain↩︎

  6. The most common standardized formats for documenting an SBOM are CycloneDX and SPDX. (source: SBOM: la chiave per la sicurezza software nella supply chain↩︎

  7. BOM-Link, BOM-Link is a formally registered URN (urn:cdx) in the CycloneDX standard that enables deep-linking to reference components, services, or vulnerabilities across different Bill of Materials (BOMs). (source: https://cyclonedx.org/capabilities/bomlink/↩︎

  8. CISA, The Cybersecurity and Infrastructure Security Agency (CISA) is the U.S. cyber defense agency that publishes official guidance on the Minimum Elements for a Software Bill of Materials (SBOM). (source: https://www.cisa.gov/news-events/news/cisa-and-partners-unveil-updated-software-bill-materials-resource-improves-transparency-security-and↩︎

  9. BSI TR-03183, BSI TR-03183 is a technical guideline by the German Federal Office for Information Security (BSI) helping manufacturers implement the EU Cyber Resilience Act (CRA) requirements, including SBOMs. (source: https://www.bsi.bund.de/dok/TR-03183-en↩︎

  10. Package URL (purl), Package URL (purl) is an Ecma standard (ECMA-427) defining a uniform URL-based syntax to reliably identify software packages across ecosystems, widely used in SBOMs and vulnerability databases. (source: https://github.com/package-url/purl-spec↩︎

  11. CPE, Common Platform Enumeration (CPE) is a standardized naming scheme maintained by NIST for identifying information technology systems, software, and hardware classes. (source: https://csrc.nist.gov/projects/security-content-automation-protocol/specifications/cpe↩︎

  12. Cosign, Cosign is a command-line utility from the Sigstore project used to cryptographically sign and verify software artifacts, such as container images and SBOMs, supporting a keyless signing workflow. (source: https://docs.sigstore.dev/cosign/↩︎

  13. Google Artifact Registry, Google Artifact Registry is a fully-managed Google Cloud service for storing, managing, and securing container images and language packages in private repositories. (source: https://cloud.google.com/blog/products/application-development/understanding-artifact-registry-vs-container-registry↩︎

  14. Artifact Analysis, Artifact Analysis is a Google Cloud service providing software composition analysis, vulnerability scanning, and metadata storage, including the generation and management of SBOMs. (source: https://docs.cloud.google.com/artifact-analysis/docs/artifact-analysis↩︎

  15. Bomctl, Bomctl is a format-agnostic Software Bill of Materials (SBOM) CLI tool by OpenSSF. It bridges the gap between SBOM generation and analysis by allowing users to fetch, store, and manipulate SBOMs. (source: https://openssf.org/projects/bomctl/↩︎

  16. GUAC, GUAC is an open-source tool that aggregates software supply chain metadata, such as SBOMs and vulnerability reports, into a graph database to map relationships and analyze security risks. (source: https://openssf.org/projects/guac/↩︎

  17. A Shared Vision of Software Bill of Materials for Cybersecurity, A joint guidance document released in September 2025 by CISA, NSA, and 19 international partners, outlining a global consensus on using SBOMs to enhance software supply chain transparency. (source: https://www.acn.gov.it/portale/en/relazioni-internazionali/sbom↩︎

  18. OpenSSF, The Open Source Security Foundation is a cross-industry initiative under the Linux Foundation that brings together developers and organizations to improve open-source software security. (source: https://openssf.org/↩︎

Domande Frequenti

Both, but with different roles. Each service generates its own SBOM as a technical artifact, while the unit of evidence required by the CRA is the product placed on the market (Annex I, Part II): an authoritative document per product version is needed to hold together the service SBOMs. Ten disconnected component SBOMs do not satisfy the obligation; a root BOM referencing them does.
It depends on release cycles, not on compliance: both are valid for the CRA. If the product has multiple services with independent releases, hierarchical compose is the only maintainable strategy, because each service regenerates independently while preserving its signature and provenance. Flat merge only works well for substantially monolithic products, with a few dozen components and a single release cadence, or when the consumer cannot resolve external references.
No. The SBOM is confidential technical documentation, not public material: it is a map of components useful to an attacker. The CRA does not mandate publishing it; the only entity that can request it is a market surveillance authority, upon reasoned request. It is released to business customers under NDA, tracking who received which version.
It is a starting point, not the finished artifact. SBOMs produced on push by a registry (e.g. Artifact Analysis on Google Artifact Registry) have retention and cleanup policies that are not aligned with the ten-year obligation (Article 13), so they must be archived in dedicated storage. Vendor SBOMs are inputs to be reconciled: normalize identifiers, integrate or link after verifying resolvability, document known unknowns. Therefore, they are not documents to be forwarded as they arrive.
No, the regulation requires a “common and machine-readable” format without prescribing a specific one. But CycloneDX and SPDX are the only ones with mature tooling for hierarchical linking and dependency relationships, so choosing one now is the safest coverage against a future Commission-prescribed format.

Get in touch

Follow us on social media
Listen to Continuous Delivery