Skip to content

Software Bill of Materials (SBOM)

This project generates SBOMs in two standard formats and distributes them through four complementary channels.


Formats

Format Standard Role File pattern
SPDX 2.3 JSON ISO/IEC 5962:2021 (Linux Foundation) Primary sbom-spdx.json
CycloneDX 1.x JSON OWASP / Ecma International (ECMA-424) Secondary sbom-cyclonedx.json

Both are generated by Syft (via anchore/sbom-action).


Distribution Channels

Channel 1 — GitHub Dependency Graph "Export SBOM"

  • What: GitHub-computed SPDX JSON based on the repository's dependency graph.
  • Where: Repository → Insights → Dependency graph → Export SBOM.
  • Who controls it: GitHub (automatic; no workflow needed).
  • Authoritative? No — computed independently by GitHub and may differ from channels 2–4.

Channel 2 — Actions Artifact (per workflow run)

  • What: SPDX and CycloneDX JSON files uploaded as workflow artifacts on every push, PR, and weekly schedule.
  • Where: Actions → workflow run → Artifacts section (sbom-spdx, sbom-cyclonedx).
  • Who controls it: sbom.yml workflow.
  • Authoritative? No — these are point-in-time snapshots per commit.

Channel 3 — Release Asset (attached to a tag/release) 🏆

  • What: SPDX and CycloneDX JSON files attached to the GitHub Release.
  • Where: Repository → Releases → select a version → Assets.
  • Who controls it: release.yml workflow (sbom job).
  • Authoritative? Yes — the release-asset SBOM is authoritative for each tagged version.

This is the SBOM that consumers, auditors, and procurement teams should reference when evaluating a specific release.

Channel 4 — Dependency Submission API (Dependency Graph enrichment)

  • What: Dependency data submitted to GitHub so the repository's Dependency Graph and Dependabot alerts reflect the full installed dependency tree (including transitive dependencies).
  • Where: Repository → Insights → Dependency graph (enriched view); Security → Dependabot alerts.
  • Who controls it: sbom.yml workflow (push to main only).
  • Authoritative? No — enriches the GitHub UI/alerts but is not a downloadable artifact.

Which SBOM Should I Use?

Use case Recommended channel
Evaluating a specific release Channel 3 — Release asset
Latest CI snapshot for development Channel 2 — Actions artifact
Quick export without cloning Channel 1 — GitHub Dependency Graph
Monitoring for new vulnerabilities Channel 4 — Dependency Submission (feeds Dependabot)

Important: Outputs May Differ

The four channels may produce different results because they use different scanners and resolve dependencies differently:

Channel Scanner Scope
1 (GitHub export) GitHub's dependency resolver Declared dependencies in manifest files
2 & 3 (Syft) Anchore Syft Installed Python environment + file-system detection
4 (Submission API) Anchore Syft (submitted data) Same as 2 & 3, surfaced in GitHub's UI

In particular:

  • Channel 1 resolves from pyproject.toml / requirements.txt without installing.
  • Channels 2–4 install the project (pip install -e .) and scan the resulting environment, so they include transitive dependencies that channel 1 may miss.

If discrepancies arise, the release-asset SBOM (channel 3) is the authoritative reference.


Workflow Details

sbom.yml — CI SBOM generation

Setting Value
Triggers push to main, PRs, weekly (Monday 13:00 UTC), manual
Repository guard vars.ENABLE_SBOM = 'true'
Artifacts sbom-spdx (SPDX JSON), sbom-cyclonedx (CycloneDX JSON)
Dependency Submission Push to main only

release.yml — Release SBOM generation

Setting Value
Triggers Tag push (v*.*.*), manual
Repository guard Same as the existing release guard (vars.ENABLE_RELEASE)
Release assets sbom-spdx.json, sbom-cyclonedx.json alongside dist artifacts

Enabling SBOMs

For the CI workflow (sbom.yml)

Set a repository variable:

Settings → Secrets and variables → Actions → Variables
  Name:  ENABLE_SBOM
  Value: true

Or replace YOURNAME/YOURREPO in the workflow file with your repo slug.

For release SBOMs (release.yml)

No additional setup needed — the SBOM job inherits the existing release repository guard (vars.ENABLE_RELEASE).


See Also