This is an early experiment. Take everything you read here with a grain of salt. It may or may not work as described.
A GitHub Action that fetches your repository's SBOM from the GitHub Dependency Graph API and submits it to the PG Atlas ingestion endpoint. Authentication is handled via GitHub OIDC — no secrets or API keys need to be configured.
jobs:
sbom:
runs-on: ubuntu-latest
permissions:
contents: read # for GitHub Dependency Graph API
id-token: write # for OIDC authentication to PG Atlas
steps:
- uses: SCF-Public-Goods-Maintenance/pg-atlas-sbom-action@3b49bfea5a8b78d04f00ad7bd633e107241a3485That's it. The action uses the default production API URL; no other inputs are required.
on:
push:
branches: [main]
release:
types: [published]Running on push to main keeps the dependency graph in PG Atlas up to date as your project evolves.
Running on release ensures a snapshot is recorded at each version boundary.
The action fetches the SBOM from GitHub's Dependency Graph API. This requires the dependency graph feature to be enabled for your repository:
Insights → Dependency graph → if you don't see it: Enable.
GitHub's dependency graph is populated from your lock files, also known as package manifests (e.g.
Cargo.lock, package-lock.json, go.sum, requirements.txt, poetry.lock). Ensure at least one
lock file is committed for the SBOM to contain dependency data.
| Input | Required | Default | Description |
|---|---|---|---|
api-url |
No | Production PG Atlas endpoint | Base URL of the PG Atlas ingestion API. Override to point at a staging environment, or your weekend experiment. |
submission-path |
No | /ingest/sbom |
API endpoint path appended to api-url for SBOM ingestion. Override if the server exposes the endpoint at a different path. |
dry-run |
No | false |
If true, fetch the SBOM and obtain the OIDC token but skip the final submission. Useful for testing your setup. |
| Output | Description |
|---|---|
sbom-path |
Path to the fetched SBOM file (sbom.spdx.json, SPDX 2.3 JSON format). |
The action uses
GitHub OIDC
to authenticate with the PG Atlas API. A short-lived, signed JWT is issued by GitHub's OIDC provider
and sent as a Bearer token. The PG Atlas API verifies the JWT's RS256 signature against GitHub's
public JWKS and checks the repository claim to identify the submitting repo.
This means:
- No secrets to configure. The only requirement is
id-token: writein your workflow'spermissionsblock. - No API keys or tokens to rotate.
- The submission is cryptographically tied to your repository — the API knows which repo submitted the SBOM.
OIDC proves the identity of the submitting repository. It does not independently verify the content of the SBOM: the repository owner/contributor could modify the submitted payload. The principal mitigations are:
- The PG Atlas reference graph cross-check flags dependency declarations that diverge significantly from the inferred graph, making inflation detectable.
- All submissions are logged with the
repositoryandactor(triggering GitHub user) OIDC claims, making falsification an attributable and auditable act. - Community review and the public leaderboard create social accountability.
Both GitHub-hosted and self-hosted runners are supported; there is no meaningful difference in the integrity guarantees between the two.
Add id-token: write to your job's permissions block:
permissions:
contents: read
id-token: writeIf your workflow has a top-level permissions block, it must also include id-token: write.
The GitHub Dependency Graph API returned 403 or 404 for your repository. Steps to resolve:
- Ensure the dependency graph is enabled (see Prerequisites).
- Ensure the workflow has
contents: readpermission (required to call the API). - For organization-owned private repos, confirm the org's security settings allow dependency graph access.
The dependency graph is populated from lock files. If your SBOM is sparse:
- Commit your lock file (
Cargo.lock,package-lock.json,go.sum, etc.) — do not add it to.gitignore. - For monorepos, all lock files in any subdirectory are detected automatically.
The OIDC token was rejected by the PG Atlas API. This should be rare; if it occurs, open an issue in this repository.
Commits must follow Conventional Commits. Install the git hook so violations are caught before they reach CI:
pip install pre-commit # or: brew install pre-commit
pre-commit install --hook-type commit-msgReleases and CHANGELOG.md are managed automatically by
release-please on every push to main.
actionlint validates GitHub Actions syntax well beyond plain YAML parsing:
# macOS / Linux with Homebrew
brew install actionlint
# Cross-platform with Go
go install github.com/rhysd/actionlint/cmd/actionlint@latestThen run from the repo root:
actionlint -verboseact lets you run the CI workflow on your machine. The easiest install on
Linux is as a gh extension:
gh extension install https://github.com/nektos/gh-actDry-run the self-test (fetches your repo's real SBOM but skips submission):
gh act push -W .github/workflows/ci.yml