SBOM Generation in CI/CD Pipelines

Why SBOMs belong in your build pipeline, what to generate on every commit versus every release, and where to find setup instructions for your CI platform.

Why build time

An SBOM describes what went into a build. The only moment that information is complete and unambiguous is while the build is happening - when the lockfile, the resolved dependency tree, the commit SHA and the build environment all exist together.

Afterwards you are reconstructing. Scanning a released artifact tells you what can be detected from the outside, which is not the same as what went in: vendored code, statically linked libraries and files copied between Docker build stages are routinely invisible to an external scan.

Generating in CI gives you five things:

  1. Consistency - every build produces an SBOM the same way, with the same tools.
  2. Automation - no manual step anyone can forget before a release.
  3. Attestation - the SBOM can be signed where it was made, tied to the pipeline run and commit that produced it.
  4. Compliance - obligations under the EU CRA, EO 14028 and FDA guidance are met continuously rather than scrambled for at audit time.
  5. Traceability - a complete path from source commit to deployed artifact.

Signing at origin

The reason build-time generation matters so much is that it is the only point at which you can sign the SBOM as the party that actually produced it.

A signature made in your pipeline binds the document to a specific commit and a specific build. Anyone can verify it later without trusting the platform that stored it. That property only holds if nothing modifies the artifact afterwards - which is why sbomify never alters an SBOM you upload.

See how to sign an SBOM.

What to generate, and when

TriggerWhat to doWhy
Every commit on the main branchGenerate, do not uploadCatches breakage early, costs nothing
Pull requestsGenerate, do not uploadVerifies the pipeline still works; CI secrets are usually unavailable to forks anyway
Tagged releasesGenerate, upload, tag a product releaseThis is the artifact customers and auditors will ask for
Container buildsGenerate from the image, not the lockfileCaptures OS packages as well as application dependencies

For what to put in the version field, see how to version SBOMs.

Set it up

The sbomify action is a CLI shipped as a container image. It selects the right generator for your ecosystem, adds your business metadata, and enriches every component from package registries - in one step. Configuration is environment variables, and they are identical on every platform.

Pick your runtime:

If your platform can run a container, it is supported even without a dedicated page.

Good practice

  • Do not fail the build on SBOM generation errors while you are still rolling this out. Once it is stable, do - a missing SBOM should be as loud as a failing test.
  • Store SBOMs as build artifacts as well as uploading them, so they are available even if an upload fails.
  • Cache the license database. It avoids re-downloading 20-50 MB on every run and reduces exposure to rate limits.
  • Set GITHUB_TOKEN whatever platform you are on. License databases come from GitHub Releases, and unauthenticated requests are throttled hard enough that enrichment quietly degrades.
  • Prefer short-lived credentials. On GitHub Actions, OIDC trusted publishing removes the long-lived token entirely.
  • Keep the audit trail. audit_trail.txt records every change the pipeline made and where it came from - archive it next to the SBOM.