Skip to content

coderpatros/action-sbom

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

action-sbom

A GitHub Action that generates a CycloneDX SBOM listing every GitHub Action used in your workflow, with each ref resolved to the exact commit SHA the runner would execute.

How it works

At the end of your workflow, this action reads the workflow file, parses every uses: entry, and calls the GitHub API to resolve tags and branch names to their actual commit SHAs - matching the resolution order used by the runner (branches take priority over tags when both exist for the same name contrary to documented behaviour). The result is written as a CycloneDX JSON file.

Each component in the SBOM includes:

  • The resolved commit SHA as the version
  • A PURL (pkg:github/owner/repo@<sha>)
  • The original ref as written in the workflow (cdx:github:action:ref)
  • A cdx:github:action:suspicious-ref: true property when the ref contains invisible or non-printable Unicode characters (a known supply-chain attack vector)

Usage

Basic - add to any workflow

Add this as the last step in any job. The action auto-detects the current workflow file via GITHUB_WORKFLOW_REF.

steps:
  - uses: actions/checkout@v4

  - name: Run tests
    run: npm test

  - name: Generate Actions SBOM
    uses: coderpatros/action-sbom@v1

Upload the SBOM as a workflow artifact

steps:
  - uses: actions/checkout@v4

  - name: Run tests
    run: npm test

  - name: Generate Actions SBOM
    id: sbom
    uses: coderpatros/action-sbom@v1
    with:
      output-file: actions-sbom.json

  - name: Upload SBOM artifact
    uses: actions/upload-artifact@v4
    with:
      name: actions-sbom
      path: ${{ steps.sbom.outputs.sbom-path }}

Inputs

Input Required Default Description
output-file No actions-sbom.json Path to write the SBOM JSON file
github-token No ${{ github.token }} Token used to resolve action refs via the GitHub API
workflow-file No (auto-detected) Workflow file to scan, relative to the repo root. Auto-detected from GITHUB_WORKFLOW_REF when omitted.

Outputs

Output Description
sbom-path Absolute path to the generated SBOM file
component-count Number of action components included in the SBOM

Local usage

A standalone CLI script is included for generating an SBOM from any workflow URL without needing to run a GitHub Actions workflow.

# Print SBOM to stdout
python3 scripts/sbom.py https://github.com/owner/repo/blob/main/.github/workflows/ci.yml

# Write to a file
python3 scripts/sbom.py https://github.com/owner/repo/blob/main/.github/workflows/ci.yml \
  -o sbom.json

# Pass a token to avoid rate limiting on public repos or to access private repos
python3 scripts/sbom.py https://github.com/owner/repo/blob/main/.github/workflows/ci.yml \
  --token "$GITHUB_TOKEN" \
  -o sbom.json

Both GitHub blob URLs (github.com/.../blob/...) and raw content URLs (raw.githubusercontent.com/...) are accepted.

Scanning all workflows in a repository

scripts/repo_sboms.py generates one SBOM per workflow file for every workflow found in a repository's .github/workflows/ directory, without needing to clone the repo.

# Write one SBOM per workflow into the current directory
python3 scripts/repo_sboms.py owner/repo

# Write SBOMs into a specific output directory
python3 scripts/repo_sboms.py owner/repo -o sboms/

# Scan a specific branch, tag, or SHA
python3 scripts/repo_sboms.py owner/repo --ref main -o sboms/

# A full GitHub URL is also accepted
python3 scripts/repo_sboms.py https://github.com/owner/repo -o sboms/

# Pass a token to avoid rate limiting or to access private repos
python3 scripts/repo_sboms.py owner/repo --token "$GITHUB_TOKEN" -o sboms/

Each workflow file ci.yml produces a corresponding ci.json SBOM in the output directory. The workflow_name field in each SBOM's metadata identifies the source file as owner/repo/.github/workflows/ci.yml.

Scanning all workflows across an organisation

scripts/org_sboms.py extends repo_sboms.py to cover an entire GitHub organisation. It discovers every repository in the org and generates one SBOM per workflow file for each repo, without needing to clone anything.

# Scan all repos in an org, write SBOMs under ./sboms/<owner>/<repo>/
python3 scripts/org_sboms.py my-org -o sboms/

# Skip archived and forked repos
python3 scripts/org_sboms.py my-org -o sboms/ --skip-archived --skip-forks

# Only scan public repos
python3 scripts/org_sboms.py my-org -o sboms/ --repo-type public

# Pass a token to avoid rate limiting or to access private repos
python3 scripts/org_sboms.py my-org --token "$GITHUB_TOKEN" -o sboms/

Output is written under <output-dir>/<owner>/<repo>/, with one JSON file per workflow — the same layout repo_sboms.py uses for a single repo. For example, .github/workflows/ci.yml in my-org/my-repo becomes sboms/my-org/my-repo/ci.json.

Option Description
-o, --output DIR Root directory to write SBOMs into (default: current directory)
-t, --token TOKEN GitHub token (default: $GITHUB_TOKEN)
--skip-archived Exclude archived repositories
--skip-forks Exclude forked repositories
--repo-type TYPE Filter by type: all, public, private, forks, sources, member (default: all)

Repos that cannot be scanned (for example because they have no .github/workflows/ directory) are skipped with a warning; the script continues scanning the remaining repos and prints a summary when done.

Security notes

Invisible Unicode characters in refs - the action detects refs that contain invisible or non-printable Unicode characters (for example a zero-width space appended to what looks like a SHA). These refs are resolved as-is against the GitHub API, because that is what the runner does - but the affected component is flagged with cdx:github:action:suspicious-ref: true in the SBOM and a warning annotation is emitted in the workflow log. An invisible-char ref can make a branch reference look visually identical to a pinned SHA, allowing an attacker-controlled branch to be silently executed.

Branch/tag priority - when a branch and a tag share the same name, the runner resolves the branch. This action matches that behaviour.

About

A GitHub Action to generate an SBOM for your GitHub Actions

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages