Git, CI/CD & GitOpsLXVIII · SBOMGeneration
SBOM generation in CI — syft, cyclonedx-bom, cdxgen
What you'll learn
- Generate a SPDX SBOM with syft in CI against the final artifact
- Generate a CycloneDX SBOM with cyclonedx-bom or cdxgen in CI
- Choose between syft, cyclonedx-bom, and cdxgen based on the artifact shape
- Wire SBOM generation into a CI pipeline with artifact upload and attestation attachment
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
The SBOM is generated at build time, against the final artifact, as a CI step. The generator scans the image, the binary, or the source tree, emits the SBOM in the format the downstream consumer needs, and the pipeline uploads the document as a CI artifact. The signing step later attaches the SBOM to the artifact digest as an attestation (LXVIII-04). This lesson is the generation step.
Three generators cover most production use cases. The choice between them is the artifact shape and the format the consumer needs.
syft: the dominant generator
anchore/syft is the SBOM generator most teams reach for. It
understands the lockfile and manifest formats of every major
ecosystem (Debian/Ubuntu, RPM, Alpine apk, npm, pip, gem, Go
modules, cargo, maven, …):
syft dir:. -o spdx-json > sbom.spdx.json
syft dir:. -o cyclonedx-json > sbom.cdx.json
The output flag (-o spdx-json, -o cyclonedx-json) chooses
the format. For container images, syft scans the layers with
the registry: prefix.
flowchart LR
A["Source tree"] --> B["syft dir:."]
A2["Final image"] --> C["syft registry:..."]
B --> D["SPDX / CycloneDX"]
C --> D
D --> E["CI artifact"]
D --> F["Attestation (next step)"]
cyclonedx-bom and cdxgen
cyclonedx-bom is the CLI the CycloneDX project ships, the
right choice for strict schema validation or when syft cannot
model a niche format:
cyclonedx-bom scan --input src --output sbom.cdx.json
cdxgen parses manifests and lockfiles directly. For
application sources (npm, pip, Go modules, Maven, Gradle), the
manifest-driven scan produces a tighter inventory:
cdxgen -o sbom.cdx.json .
cdxgen is excellent for application sources and weaker for OS-package inventories; teams that rely on a base image’s OS packages need a syft scan alongside.
CI integration
A CI pipeline generates and uploads the SBOM. The pipeline runs the generator twice with two output flags and uploads both; the signing step attaches one — or both — to the artifact digest as an attestation (LXVIII-04):
Production discipline
- Generate the SBOM in CI, on the runner, against the final artifact.
- Emit the format the downstream consumer ingests natively and validate against the official schema as a CI gate.
- Upload the SBOM as a CI artifact as a backstop, but attach it as an attestation for durability.
Cross-course references
- Git, CI/CD & GitOps — Part LXVIII-04 (SBOM Distribution and Attestation) is the next step: the SBOM moves from the CI artifact to the signed attestation on the digest.
Quiz
Knowledge check · 4 questions
Q1. Which generator is the right default for most teams and why?
Q2. A CI pipeline that runs `syft dir:.` against the source tree produces a SBOM that includes the OS packages inherited from the base image.
Q3. Name the three production-grade SBOM generators covered in this lesson.
Q4. Diagnose why the SBOM misses the openSSL CVE and recommend the fix.
Team T builds a Node service from a Debian-slim base. The SBOM step runs `syft dir:$GITHUB_WORKSPACE -o cyclonedx-json > sbom.cdx.json` against the source tree. A CVE is published against the OpenSSL shipped in the base. The matcher reports no exposure.
Passing score: 75%. Answers are checked in this browser.