📦 GitHub SBOM Generation Action
A comprehensive GitHub Action for generating Software Bill of Materials (SBOM) using the advanced-security/gh-sbom CLI extension with support for multiple formats, licensing information, and enterprise integration.
✨ Features
- 📋 Multiple SBOM Formats - Generate SPDX or CycloneDX format SBOMs
- 🔍 Repository Flexibility - Support for any GitHub repository (current or specified)
- 📄 License Information - Optional license details from ClearlyDefined.io for CycloneDX
- 💾 Flexible Output - Output to file or stdout with multiple format options
- 🛡️ Secure Token Handling - Automatic token masking and secure authentication
- 📊 Detailed Component Analysis - Component counting and comprehensive reporting
- 🚀 Cross-Platform Support - Works on Linux, macOS, and Windows runners
- ✅ Enterprise Ready - Support for GitHub Enterprise Server and private repositories
🚀 Basic Usage
Generate an SPDX SBOM for the current repository:
- name: "Generate SBOM"
uses: laerdal/github_actions/gh-sbom@main
- name: "Generate CycloneDX SBOM with licenses"
uses: laerdal/github_actions/gh-sbom@main
with:
format: "cyclonedx"
include-license: "true"
output-file: "sbom.json"
- name: "Generate SBOM for specific repository"
uses: laerdal/github_actions/gh-sbom@main
with:
repository: "owner/repo-name"
format: "spdx"
output-file: "dependency-sbom.json"
show-summary: "true"
🔧 Advanced Usage
Full configuration with all available options:
- name: "Advanced SBOM generation"
uses: laerdal/github_actions/gh-sbom@main
with:
repository: "advanced-security/gh-sbom"
format: "cyclonedx"
include-license: "true"
output-file: "reports/sbom-cyclonedx.json"
github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
show-summary: "true"
🔐 Permissions Required
This action requires standard repository permissions:
permissions:
contents: read # Required to access repository and dependency graph
security-events: read # Required for dependency graph access
For private repositories or cross-repo access:
permissions:
contents: read
security-events: read
metadata: read
🏗️ CI/CD Example
Complete workflow for SBOM generation and security scanning:
name: "Security - SBOM Generation"
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
schedule:
- cron: "0 6 * * 1" # Weekly on Mondays
permissions:
contents: read
security-events: read
jobs:
generate-sbom:
runs-on: ubuntu-latest
steps:
- name: "📥 Checkout repository"
uses: actions/checkout@v4
- name: "📋 Generate SPDX SBOM"
id: spdx-sbom
uses: laerdal/github_actions/gh-sbom@main
with:
format: "spdx"
output-file: "sbom-spdx.json"
show-summary: "true"
- name: "📋 Generate CycloneDX SBOM with licenses"
id: cyclonedx-sbom
uses: laerdal/github_actions/gh-sbom@main
with:
format: "cyclonedx"
include-license: "true"
output-file: "sbom-cyclonedx.json"
show-summary: "true"
- name: "📊 Report SBOM statistics"
run: |
echo "SPDX SBOM components: ${{ steps.spdx-sbom.outputs.component-count }}"
echo "CycloneDX SBOM components: ${{ steps.cyclonedx-sbom.outputs.component-count }}"
- name: "📁 Upload SBOM artifacts"
uses: actions/upload-artifact@v4
with:
name: "sbom-reports-${{ github.sha }}"
path: |
sbom-spdx.json
sbom-cyclonedx.json
signed-sbom-spdx.json
retention-days: 90
📋 Inputs
| Input | Description | Required | Default | Example |
|---|---|---|---|---|
repository |
Repository to generate SBOM for (format: owner/repo) | ❌ No | '' |
owner/repo-name, microsoft/vscode |
format |
SBOM format to generate | ❌ No | 'spdx' |
spdx, cyclonedx |
include-license |
Include license information for CycloneDX format | ❌ No | 'false' |
true, false |
output-file |
Path to save the generated SBOM file | ❌ No | '' |
sbom.json, ./reports/sbom.spdx |
github-token |
GitHub token for authentication | ❌ No | ${{ github.token }} |
${{ secrets.GITHUB_TOKEN }} |
show-summary |
Whether to show the action summary | ❌ No | 'false' |
true, false |
📤 Outputs
| Output | Description | Type | Example |
|---|---|---|---|
sbom-format |
Format of the generated SBOM | string |
spdx, cyclonedx |
output-file |
Path to the generated SBOM file | string |
sbom.json |
component-count |
Number of components found in the SBOM | string |
42 |
exit-code |
Exit code of the gh-sbom command | string |
0 |
file-size |
Size of generated SBOM file in bytes | string |
15728 |
🔗 Related Actions
| Action | Purpose | Repository |
|---|---|---|
| 📋 dotnet-cyclonedx | Generate .NET SBOMs | laerdal/github_actions/dotnet-cyclonedx |
| 🛡️ Security Actions | GitHub security tooling | Various security actions |
💡 Examples
Basic SBOM Generation
- name: "Generate SPDX SBOM for current repo"
uses: laerdal/github_actions/gh-sbom@main
with:
format: "spdx"
output-file: "sbom.spdx.json"
Multi-Format Generation
- name: "Generate both SBOM formats"
strategy:
matrix:
format: ['spdx', 'cyclonedx']
steps:
- name: "Generate ${{ matrix.format }} SBOM"
uses: laerdal/github_actions/gh-sbom@main
with:
format: ${{ matrix.format }}
include-license: ${{ matrix.format == 'cyclonedx' && 'true' || 'false' }}
output-file: "sbom-${{ matrix.format }}.json"
show-summary: "true"
Cross-Repository Analysis
- name: "Analyze multiple repositories"
strategy:
matrix:
repo:
- "owner/repo1"
- "owner/repo2"
- "owner/repo3"
steps:
- name: "Generate SBOM for ${{ matrix.repo }}"
uses: laerdal/github_actions/gh-sbom@main
with:
repository: ${{ matrix.repo }}
format: "spdx"
output-file: "sbom-${{ matrix.repo | replace('/', '-') }}.json"
github-token: ${{ secrets.CROSS_REPO_TOKEN }}
Enterprise Workflow
- name: "Enterprise SBOM workflow"
uses: laerdal/github_actions/gh-sbom@main
with:
repository: ${{ github.repository }}
format: "cyclonedx"
include-license: "true"
output-file: "./compliance/sbom-cyclonedx.json"
github-token: ${{ secrets.ENTERPRISE_GITHUB_TOKEN }}
show-summary: "true"
- name: "Validate SBOM compliance"
run: |
# Custom validation logic for enterprise compliance
jq '.components | length' ./compliance/sbom-cyclonedx.json
- name: "Archive for compliance"
uses: actions/upload-artifact@v4
with:
name: "compliance-sbom-${{ github.run_id }}"
path: ./compliance/sbom-cyclonedx.json
retention-days: 2555 # 7 years for compliance
Conditional SBOM Generation
- name: "Check if SBOM generation needed"
id: check-changes
run: |
if git diff --name-only HEAD~1 | grep -E '\.(csproj|sln|packages\.config|package\.json|requirements\.txt|go\.mod|Cargo\.toml)$'; then
echo "needs-sbom=true" >> $GITHUB_OUTPUT
else
echo "needs-sbom=false" >> $GITHUB_OUTPUT
fi
- name: "Generate SBOM on dependency changes"
if: steps.check-changes.outputs.needs-sbom == 'true'
uses: laerdal/github_actions/gh-sbom@main
with:
format: "spdx"
output-file: "updated-sbom.json"
show-summary: "true"
📊 Format Specifications
SPDX Format
- API Source: Dependency Graph SBOM API
- Generation: Server-side (faster performance)
- License Information: Always included
- Repository Size: Works with large repositories
- Format Version: SPDX 2.3 compliant JSON
- Best For: Production workflows, large repositories, enterprise use
CycloneDX Format
- API Source: Dependency Graph GraphQL API
- Generation: Client-side assembly
- License Information: Optional from ClearlyDefined
- Repository Size: May have limitations with very large repositories
- Format Version: CycloneDX 1.4 compliant JSON
- Best For: Detailed license analysis, smaller repositories, development workflows
📋 Requirements
GitHub CLI and Extension
- GitHub CLI (gh): Pre-installed on all GitHub-hosted runners
- gh-sbom extension: Automatically installed by the action
- Version Compatibility: Latest stable versions
Repository Requirements
Dependency Graph Enabled: Target repository must have Dependency Graph enabled
- Navigate to:
Settings → Security & analysis → Dependency graph - Enable if not already active
- Navigate to:
Supported Package Managers:
- npm (JavaScript/Node.js)
- pip (Python)
- Maven (Java)
- Go modules
- RubyGems (Ruby)
- GitHub Actions
- .NET NuGet packages
Authentication Requirements
- GitHub Token: Required for authentication (uses
GITHUB_TOKENby default) - Private Repositories: Token needs
reposcope - Cross-Repository: Token needs access to target repositories
- Enterprise: Compatible with GitHub Enterprise Server 3.9+
🐛 Troubleshooting
Common Issues
Dependency Graph Not Enabled
Problem: No dependencies found error
If you own this repository, check if Dependency Graph is enabled:
https://github.com/owner/repo/settings/security_analysis
Solution: Enable Dependency Graph in repository settings:
- name: "Check dependency graph status"
run: |
echo "Verify Dependency Graph is enabled at:"
echo "https://github.com/${{ github.repository }}/settings/security_analysis"
Permission Errors
Problem: Action fails with authentication errors
Solutions:
- Ensure
GITHUB_TOKENhas required permissions:
permissions:
contents: read
security-events: read
metadata: read
- For private repositories, use a token with
reposcope:
- name: "Generate SBOM for private repo"
uses: laerdal/github_actions/gh-sbom@main
with:
repository: "private-org/private-repo"
github-token: ${{ secrets.PRIVATE_REPO_TOKEN }}
Large Repository Timeouts
Problem: CycloneDX generation times out on large repositories
Solutions:
- Use SPDX format instead:
- name: "Generate SBOM for large repo"
uses: laerdal/github_actions/gh-sbom@main
with:
format: "spdx" # Server-side generation
output-file: "large-repo-sbom.json"
- Consider running on more powerful runners:
runs-on: ubuntu-latest-8-cores # Use larger runner
Extension Installation Failures
Problem: GitHub CLI or extension installation fails
Solutions:
Check runner OS compatibility and network connectivity
Pre-install dependencies:
- name: "Pre-install gh-sbom extension"
run: |
gh extension install advanced-security/gh-sbom
gh sbom --version
No Components Found
Problem: SBOM generated but shows zero components
Solutions:
- Verify supported package managers are in use
- Check repository has manifest files (package.json, requirements.txt, etc.)
- Ensure dependencies are committed to repository
- name: "List package manifests"
run: |
find . -name "package.json" -o -name "requirements.txt" -o -name "*.csproj" -o -name "go.mod" | head -10
Debug Mode
Enable comprehensive debugging:
- name: "Debug SBOM generation"
uses: laerdal/github_actions/gh-sbom@main
with:
format: "spdx"
output-file: "debug-sbom.json"
show-summary: "true"
env:
ACTIONS_STEP_DEBUG: true
GH_DEBUG: true
Error Codes
| Exit Code | Description | Action |
|---|---|---|
0 |
Success | Continue workflow |
1 |
General error | Check inputs and permissions |
2 |
Network/API error | Retry or check connectivity |
3 |
File system error | Check file paths and permissions |
🔧 Advanced Configuration
Enterprise GitHub Setup
- name: "Generate SBOM on GitHub Enterprise"
uses: laerdal/github_actions/gh-sbom@main
with:
repository: "enterprise-org/enterprise-repo"
format: "spdx"
output-file: "enterprise-sbom.json"
github-token: ${{ secrets.GHES_TOKEN }}
env:
GH_HOST: "github.enterprise.com"
Batch SBOM Generation
- name: "Generate SBOMs for organization"
run: |
for repo in $(gh repo list myorg --json name --jq '.[].name'); do
echo "Generating SBOM for myorg/$repo"
gh sbom repo "myorg/$repo" --format spdx > "sbom-$repo.json" || echo "Failed for $repo"
done
env:
GH_TOKEN: ${{ secrets.ORG_ACCESS_TOKEN }}
Comparison Workflow
- name: "Compare SBOM formats"
run: |
# Generate both formats
gh sbom repo ${{ github.repository }} --format spdx > sbom-spdx.json
gh sbom repo ${{ github.repository }} --format cyclonedx --include-license > sbom-cyclonedx.json
# Compare component counts
spdx_count=$(jq '.packages | length' sbom-spdx.json)
cyclonedx_count=$(jq '.components | length' sbom-cyclonedx.json)
echo "SPDX components: $spdx_count"
echo "CycloneDX components: $cyclonedx_count"
📊 Comparison with Other SBOM Tools
| Feature | gh-sbom Action | Other Tools |
|---|---|---|
| GitHub Integration | ✅ Native integration | ⚠️ Requires complex setup |
| Server-side Generation | ✅ SPDX format | ❌ Usually client-side only |
| License Information | ✅ Built-in support | ⚠️ Varies by tool |
| Large Repositories | ✅ SPDX supports any size | ❌ Often limited |
| Multiple Formats | ✅ SPDX & CycloneDX | ⚠️ Usually single format |
| Zero Configuration | ✅ Works out-of-box | ❌ Requires extensive setup |
| Enterprise Support | ✅ GitHub Enterprise ready | ⚠️ Limited enterprise features |
📄 License
This action is part of the GitHub Actions collection by Francois Raminosona.
💡 Tip: Combine this action with our SBOM signing and publishing actions for complete supply chain security workflows.