Software Bill of Materials (SBOM) for Enterprise DevSecOps
Prerequisites
- Working knowledge of CI/CD pipelines and container registries
- Basic familiarity with software supply chain security and vulnerability management
Steps
A Software Bill of Materials (SBOM) gives enterprises a machine-readable inventory of software components, dependencies, and provenance across applications and containers. This guide explains SBOM architecture, implementation, hardening, and operational practices for large-scale DevSecOps programs.
Overview
A Software Bill of Materials (SBOM) is a structured inventory of software components, including direct and transitive dependencies, versions, licenses, hashes, and supplier metadata. Common formats include CycloneDX and SPDX, and common generators include Syft, Trivy, and vendor tooling built into CI/CD and artifact platforms.
Enterprises use SBOMs to improve supply chain visibility, accelerate vulnerability response, support license compliance, and meet requirements from frameworks such as NIST SSDF, EO 14028, and sector-specific procurement controls. In practice, an SBOM becomes most valuable when it is generated automatically in the build pipeline, signed, stored with the artifact, and correlated with vulnerability intelligence.
Architecture
Core components typically include:
- Source repositories with dependency manifests such as
package-lock.json,pom.xml, orgo.sum - CI/CD runners that build artifacts and generate SBOMs
- Artifact registries such as JFrog Artifactory, GitHub Container Registry, or Amazon ECR
- SBOM storage and signing using object storage, OCI attestations, or registry attachments
- Vulnerability intelligence from Grype, Trivy DB, OSV, or commercial scanners
- Governance layer for policy, retention, and audit evidence
Deployment models:
- Pipeline-native: generate SBOM during every build and attach to the artifact
- Registry-centric: scan existing images in registries and backfill SBOMs
- Hybrid: generate at build time and continuously re-evaluate against new CVEs
View as text
[Developer] ---- 1. commit ----> [Git Repository] [Git Repository] ---- 2. trigger ----> [CI Pipeline] [CI Pipeline] ---- 3. build ----> [Container Image] [CI Pipeline] ---- 4. generate SBOM ----> [CycloneDX/SPDX File] [CI Pipeline] ---- 5. sign attestation ----> [Cosign] [Container Image] ---- 6. push ----> [Artifact Registry] [CycloneDX/SPDX File] ---- 7. attach/store ----> [Artifact Registry] [Artifact Registry] ---- 8. scan ----> [Vulnerability Engine] [Vulnerability Engine] ---- 9. findings ----> [Security Dashboard] [Security Dashboard] ---- 10. policy gate ----> [Release Approval]
Implementation Guide
- Install tooling on the CI runner.
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
curl -sSfL https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 -o /usr/local/bin/cosign
chmod +x /usr/local/bin/cosign
- Build the container image.
docker build -t registry.example.com/payments/api:1.4.2 .
docker push registry.example.com/payments/api:1.4.2
- Generate an SBOM in CycloneDX JSON.
syft registry.example.com/payments/api:1.4.2 -o cyclonedx-json > sbom.cdx.json
- Scan the image and optionally the SBOM.
grype registry.example.com/payments/api:1.4.2 --fail-on high
grype sbom:sbom.cdx.json --add-cpes-if-none
- Sign the image and attach attestation.
export COSIGN_EXPERIMENTAL=1
cosign sign --key env://COSIGN_PRIVATE_KEY registry.example.com/payments/api:1.4.2
cosign attest --key env://COSIGN_PRIVATE_KEY --predicate sbom.cdx.json --type cyclonedx registry.example.com/payments/api:1.4.2
- Enforce policy in CI with a minimal gate: fail on critical vulnerabilities or unsigned artifacts.
Example CI config file:
name: sbom-pipeline
on: [push]
jobs:
build-sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker build -t ghcr.io/acme/payments:${{ github.sha }} .
- run: syft dir:. -o spdx-json > source.spdx.json
- run: syft ghcr.io/acme/payments:${{ github.sha }} -o cyclonedx-json > image.cdx.json
- run: grype sbom:image.cdx.json --fail-on critical
- run: cosign attest --yes --key env://COSIGN_PRIVATE_KEY --predicate image.cdx.json --type cyclonedx ghcr.io/acme/payments:${{ github.sha }}
Code Examples
syft dir:. -o cyclonedx-json > app-sbom.json
jq '.metadata.component.name, .components | length' app-sbom.json
apiVersion: v1
kind: ConfigMap
metadata:
name: sbom-policy
data:
policy.yaml: |
fail_on_severity: critical
require_signature: true
allowed_licenses:
- Apache-2.0
- MIT
- BSD-3-Clause
import json
with open("sbom.cdx.json") as f:
sbom = json.load(f)
components = sbom.get("components", [])
critical_pkgs = [c.get("name") for c in components if c.get("publisher") == "openssl"]
print({"component_count": len(components), "watchlist": critical_pkgs})
Security Hardening
- Sign SBOMs and artifacts with Cosign or Notation to prevent tampering
- Encrypt registry traffic with TLS 1.2+ and enforce private endpoints where possible
- Restrict access using least-privilege RBAC for CI runners, registries, and security dashboards
- Store immutable evidence in versioned object storage or WORM-capable repositories
- Correlate SBOMs with provenance using SLSA attestations and build metadata
- Minimize secrets exposure by using OIDC workload identity instead of static registry credentials
- Retain historical SBOMs so newly disclosed CVEs can be mapped to released versions
Comparison
| Product | Pricing | Deployment | Scalability | Security |
|---|---|---|---|---|
| Anchore Enterprise | Commercial subscription | Self-hosted or SaaS-assisted | Strong for large image fleets and policy workflows | SBOM, policy engine, RBAC, signed metadata support |
| Snyk Open Source | Per-seat commercial pricing | SaaS with SCM and CI integrations | Excellent for developer-led scanning across many repos | Strong vuln intel, policy controls, SSO, audit trails |
| JFrog Xray | Commercial platform pricing | SaaS or self-hosted with Artifactory | High scalability for registry-centric enterprises | Deep artifact governance, watches, RBAC, signed artifact workflows |
Troubleshooting
- Unsupported image reference
[0000] ERROR failed to catalog: unable to parse image reference "registry.example.com/payments/api"
[0000] FATAL cataloging error: no tag or digest specified
Fix: use a fully qualified tag or digest such as registry.example.com/payments/api:1.4.2.
- Grype database update failure
2026-02-10T08:14:22Z ERROR failed to update vulnerability database: unable to download db: Get "https://toolbox-data.anchore.io/grype/databases/listing.json": x509: certificate signed by unknown authority
Fix: install the enterprise CA bundle on the runner and set SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt.
- Cosign key parsing error
Error: loading private key: decrypting key: invalid password
main.go:74: error during command execution: loading private key
Fix: verify COSIGN_PASSWORD, confirm the key format, and rotate the signing key if the secret was corrupted.
Best Practices
Do
- Generate SBOMs for source and built artifacts; compare both to catch build-time drift
- Attach SBOMs to OCI images as attestations rather than storing them only in CI logs
- Re-scan historical SBOMs when new CVEs are published
- Normalize on CycloneDX or SPDX across teams for easier aggregation
- Include license and supplier metadata for legal and procurement workflows
Don't
- Do not treat SBOM generation as a one-time compliance exercise
- Do not rely only on package manifests; container layers and OS packages matter
- Do not allow unsigned SBOMs into release workflows
- Do not delete old SBOMs after deployment; they are needed for retrospective impact analysis
Concrete example: if openssl CVEs are disclosed, query stored SBOMs for all releases containing affected versions, map them to deployed environments, and trigger patch pipelines based on business criticality.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI