Safeguard
DevSecOps

SBOMs in the CI/CD Pipeline: From Generation to Actually Useful

Generating an SBOM is easy. Making it answer 'are we affected by this CVE, and where?' in seconds is the part most teams skip. Here is how to build SBOMs into your pipeline so they earn their keep.

Priya Mehta
DevSecOps Lead
6 min read

Most teams that "do SBOMs" produce a CycloneDX file at build time, upload it as a pipeline artifact, and never look at it again. The file exists, a compliance checkbox is ticked, and when a critical CVE drops in a widely-used library at 2 a.m., the security team still spends the next six hours grepping through repositories to figure out which services are affected. A generated-and-forgotten SBOM is theater. A stored, signed, and continuously-queried SBOM is the difference between a five-minute impact assessment and a weekend fire drill.

This is how to build SBOMs into a pipeline so they actually do the one job they exist for: answering what is in our software, and are we affected by the vulnerability that just got disclosed?

What an SBOM is and why the format matters

A Software Bill of Materials is a formal, machine-readable inventory of every component in a piece of software — direct dependencies, transitive dependencies, versions, and often their license and supplier. Two formats dominate in 2026: CycloneDX (OWASP, security-focused, rich vulnerability and dependency-relationship support) and SPDX (Linux Foundation, an ISO/IEC standard, strong on licensing and provenance). Both are fine; pick one and be consistent. What matters far more than the format war is that the SBOM is generated from the actually resolved dependency tree of a real build, not from a manifest file that lists ranges rather than the exact versions that shipped.

The four stages of a useful SBOM pipeline

Stage 1 — Generate at build, from the real artifact

Generate the SBOM at the moment of build, against the fully resolved lockfile or the built artifact, so transitive dependencies and pinned versions are captured exactly as they ship. Generating from a manifest before resolution misses the transitive tree — which is precisely where supply-chain risk hides.

# ci: generate an sbom at build time
sbom-generate:
  stage: build
  script:
    - safeguard sbom generate \
        --format cyclonedx \
        --output sbom.cdx.json \
        --from ./dist            # the built artifact, not the manifest
  artifacts:
    paths: [sbom.cdx.json]

For containers, generate the SBOM against the final image so OS packages and language dependencies are both included — a language-only SBOM misses the Debian or Alpine packages that carry their own CVE stream.

Stage 2 — Sign and attest

An unsigned SBOM is untrustworthy: if it can be edited after the fact, it cannot serve as evidence of what shipped. Attach the SBOM to the artifact as a signed attestation using Sigstore's cosign, which ties the SBOM cryptographically to the exact image or artifact digest.

sbom-attest:
  stage: build
  script:
    - cosign attest --predicate sbom.cdx.json \
        --type cyclonedx \
        $IMAGE@$DIGEST

This is also what closes the loop for frameworks like SLSA and the US executive-order guidance on software provenance — the SBOM becomes verifiable evidence, not just a file someone produced once.

Stage 3 — Store centrally and version

A pipeline artifact that expires in 30 days is useless for answering a question about a CVE disclosed next quarter. Store every SBOM in a central, queryable repository keyed by artifact digest and version, and keep the history. The point is to be able to ask "which versions of which services ever contained log4j-core between these versions?" — a question that requires retained, indexed SBOMs, not ephemeral build artifacts.

Stage 4 — Continuously match against new vulnerabilities

This is the stage that turns SBOMs from compliance paperwork into operational value, and the stage almost everyone skips. Re-evaluate your stored SBOMs against vulnerability feeds continuously, so when a new CVE is published, you are alerted about affected services immediately — with no rebuild and no code change. The component was clean when you shipped; the vulnerability is new; the SBOM lets you detect that instantly.

# scheduled: match stored SBOMs against fresh advisories
sbom-watch:
  stage: monitor
  rules:
    - if: '$CI_PIPELINE_SOURCE == "schedule"'   # e.g. hourly
  script:
    - safeguard sbom scan \
        --all-stored \
        --against latest-advisories \
        --notify slack

The SBOM maturity checklist

CapabilityTheaterUseful
GenerationFrom manifest, occasionallyFrom resolved build artifact, every build
ScopeLanguage deps onlyLanguage + OS + container layers
IntegrityUnsigned fileSigned attestation bound to digest
StoragePipeline artifact, expiresCentral, versioned, queryable, retained
UsageGenerated once, ignoredContinuously matched to new CVEs
Impact query timeHours of greppingSeconds

If your program lives in the left column, you have SBOM compliance but not SBOM value.

Common mistakes to avoid

  • Generating from the manifest, not the build. You miss the transitive tree and the exact versions.
  • Container SBOMs that ignore OS packages. Half your CVE exposure is in the base image.
  • Never re-scanning. An SBOM's value compounds over time only if you keep matching it to new advisories.
  • No VEX. Pair SBOMs with VEX (Vulnerability Exploitability eXchange) statements so you can formally record "affected but not exploitable" and stop re-triaging the same non-issue.
  • One SBOM for a monorepo. Generate per-artifact so impact analysis maps to a deployable unit.

How Safeguard helps

Safeguard treats the SBOM as a living asset, not a build byproduct. SBOM Studio generates CycloneDX and SPDX SBOMs from the resolved build artifact — including container OS layers — signs them, stores them centrally and versioned, and continuously re-matches every stored SBOM against fresh advisories so "are we affected?" is a query that returns in seconds. SCA layers reachability on top, so when a new CVE hits a component in your SBOM, you learn not just whether you ship it but whether you actually call the vulnerable code. When a fix exists, auto-fix opens the remediation pull request, and the whole flow runs from the Safeguard CLI as a step in your existing pipeline.

Compare continuous SBOM operations to bolt-on generation in our platform comparison, then get started free or read the documentation.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.