๐ CycloneDX SBOM Generator Action
A comprehensive GitHub Action for generating Software Bill of Materials (SBOM) files using the CycloneDX .NET Global Tool with extensive configuration options and cross-platform support.
โจ Features
- ๐ SBOM Generation - Creates CycloneDX-compliant Software Bill of Materials
- ๐ง Multiple Formats - Supports XML, JSON, and UnsafeJSON output formats
- ๐ฏ Smart Detection - Handles .sln, .csproj, packages.config, and directory scanning
- ๐ GitHub Integration - License resolution using GitHub API
- ๐ฆ Dependency Management - Excludes dev/test dependencies with filtering options
- ๐ก๏ธ Security-First - Automatic masking of sensitive tokens and passwords
- โก Performance Optimized - Configurable timeouts and restore options
- ๐ Cross-Platform - Works on Windows, Linux, and macOS runners
๐ Basic Usage
Minimal configuration to generate an SBOM:
- name: "Generate SBOM"
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
path: "./src/MyProject.csproj"
- name: "Generate JSON SBOM"
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
path: "./MySolution.sln"
output-format: "Json"
- name: "Generate SBOM for entire directory"
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
working-directory: "./src"
recursive: "true"
๐ง Advanced Usage
Full configuration with all available options:
- name: "Advanced SBOM generation"
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
path: "./src/MyApp/MyApp.csproj"
working-directory: "./backend"
framework: "net8.0"
runtime: "linux-x64"
output: "./sbom"
filename: "software-bom.json"
output-format: "Json"
exclude-dev: "true"
exclude-test-projects: "true"
recursive: "true"
enable-github-licenses: "true"
github-bearer-token: "${{ secrets.GITHUB_TOKEN }}"
set-name: "MyApplication"
set-version: "1.2.3"
set-type: "Application"
exclude-filter: "TestFramework@1.0.0,MockLibrary@2.1.0"
dotnet-command-timeout: "600000"
global: "true"
show-summary: "true"
๐ Permissions Required
This action requires standard repository permissions:
permissions:
contents: read # Required to checkout repository code
For GitHub license resolution, add:
permissions:
contents: read
metadata: read # Optional: for enhanced GitHub license resolution
Note: When using
github-bearer-token, theGITHUB_TOKENsecret provides sufficient permissions for license resolution.
๐๏ธ CI/CD Example
Complete workflow for .NET SBOM generation:
name: "SBOM Generation Pipeline"
on:
push:
branches: ["main", "develop"]
pull_request:
branches: ["main"]
permissions:
contents: read
metadata: read
jobs:
generate-sbom:
runs-on: ubuntu-latest
steps:
- name: "๐ฅ Checkout repository"
uses: actions/checkout@v4
- name: "๐ง Setup .NET"
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"
- name: "๐ฆ Restore dependencies"
uses: laerdal/github_actions/dotnet@main
with:
command: "restore"
- name: "๐ Generate SBOM"
id: generate-sbom
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
path: "./src/MyApp.sln"
output: "./artifacts/sbom"
output-format: "Json"
filename: "software-bill-of-materials.json"
exclude-dev: "true"
exclude-test-projects: "true"
enable-github-licenses: "true"
github-bearer-token: "${{ secrets.GITHUB_TOKEN }}"
set-name: "${{ github.repository }}"
set-version: "${{ github.ref_name }}"
show-summary: "true"
- name: "๐ค Upload SBOM artifact"
uses: actions/upload-artifact@v4
with:
name: "software-bill-of-materials"
path: ${{ steps.generate-sbom.outputs.sbom-path }}
- name: "๐ Validate SBOM generation"
run: |
echo "SBOM generated: ${{ steps.generate-sbom.outputs.is-sbom-generated }}"
echo "SBOM location: ${{ steps.generate-sbom.outputs.sbom-path }}"
ls -la ${{ steps.generate-sbom.outputs.sbom-path }}
๐ Inputs
| Input | Description | Required | Default | Example |
|---|---|---|---|---|
path |
Path to .sln, .csproj, packages.config file or directory | โ No | "" |
./src/MyProject.csproj |
working-directory |
Working directory for command execution | โ No | "." |
./backend |
framework |
Target framework to use | โ No | "" |
net8.0, net6.0 |
runtime |
Target runtime identifier | โ No | "" |
win-x64, linux-x64 |
output |
Directory to write the SBOM | โ No | "" |
./sbom, ./artifacts |
filename |
Custom filename for the SBOM | โ No | "" |
software-bom.xml, app-sbom.json |
output-format |
SBOM output format | โ No | "Auto" |
Auto, Json, UnsafeJson, Xml |
exclude-dev |
Exclude development dependencies | โ No | "false" |
true, false |
exclude-test-projects |
Exclude test projects | โ No | "false" |
true, false |
recursive |
Recursively scan project references | โ No | "false" |
true, false |
no-serial-number |
Omit serial number from SBOM | โ No | "false" |
true, false |
enable-github-licenses |
Enable GitHub license resolution | โ No | "false" |
true, false |
github-username |
GitHub username for license resolution | โ No | "" |
myusername |
github-token |
GitHub personal access token | โ No | "" |
${{ secrets.GITHUB_TOKEN }} |
github-bearer-token |
GitHub bearer token (recommended) | โ No | "" |
${{ secrets.GITHUB_TOKEN }} |
url |
Alternative NuGet repository URL | โ No | "" |
https://nuget.example.com/v3/index.json |
baseUrlUsername |
Alternative NuGet repository username | โ No | "" |
nuget-user |
baseUrlUserPassword |
Alternative NuGet repository password | โ No | "" |
${{ secrets.NUGET_PASSWORD }} |
isBaseUrlPasswordClearText |
NuGet password is cleartext | โ No | "false" |
true, false |
disable-package-restore |
Disable package restore | โ No | "false" |
true, false |
disable-hash-computation |
Disable hash computation | โ No | "false" |
true, false |
dotnet-command-timeout |
Command timeout in milliseconds | โ No | "300000" |
600000, 900000 |
include-project-references |
Include project references as components | โ No | "false" |
true, false |
set-name |
Override BOM component name | โ No | "" |
MyApplication |
set-version |
Override BOM component version | โ No | "" |
1.0.0, 2.1.3 |
set-type |
Override BOM component type | โ No | "Application" |
Library, Framework |
set-nuget-purl |
Override BOM ref and PURL as NuGet package | โ No | "false" |
true, false |
exclude-filter |
Dependencies to exclude (name@version) | โ No | "" |
TestLib@1.0.0,MockFramework@2.0.0 |
base-intermediate-output-path |
Custom build environment folder | โ No | "" |
./custom-obj |
import-metadata-path |
Metadata template file path | โ No | "" |
./templates/metadata.json |
global |
Install CycloneDX global tool if needed | โ No | "true" |
true, false |
show-summary |
Display action summary | โ No | "false" |
true, false |
๐ค Outputs
| Output | Description | Type | Example |
|---|---|---|---|
exit-code |
Exit code of the CycloneDX command | string |
0, 1 |
executed-command |
Full command that was executed | string |
dotnet tool run CycloneDX ./src --output-format Json |
sbom-path |
Path to the generated SBOM file | string |
./sbom/bom.json |
is-sbom-generated |
Whether SBOM was successfully generated | string |
true, false |
๐ Related Actions
| Action | Purpose | Repository |
|---|---|---|
| ๐ dotnet | Execute .NET CLI commands | laerdal/github_actions/dotnet |
| ๐ง dotnet-tool-install | Install .NET global tools | laerdal/github_actions/dotnet-tool-install |
| ๐งช dotnet-test | Enhanced .NET testing | laerdal/github_actions/dotnet-test |
๐ก Examples
Different Output Formats
- name: "Generate XML SBOM"
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
path: "./src/MyApp.csproj"
output-format: "Xml"
filename: "software-bom.xml"
- name: "Generate JSON SBOM"
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
path: "./src/MyApp.csproj"
output-format: "Json"
filename: "software-bom.json"
Multi-Project Solution
- name: "Generate SBOM for entire solution"
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
path: "./MySolution.sln"
exclude-test-projects: "true"
exclude-dev: "true"
recursive: "true"
output: "./artifacts/sbom"
Framework-Specific SBOM
strategy:
matrix:
framework: ["net6.0", "net8.0"]
steps:
- name: "Generate SBOM for ${{ matrix.framework }}"
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
path: "./src/MultiTarget.csproj"
framework: ${{ matrix.framework }}
filename: "sbom-${{ matrix.framework }}.json"
output-format: "Json"
GitHub License Resolution
- name: "Generate SBOM with license information"
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
path: "./src/MyApp.csproj"
enable-github-licenses: "true"
github-bearer-token: "${{ secrets.GITHUB_TOKEN }}"
output-format: "Json"
Custom NuGet Repository
- name: "Generate SBOM from private NuGet"
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
path: "./src/MyApp.csproj"
url: "https://nuget.company.com/v3/index.json"
baseUrlUsername: "${{ secrets.NUGET_USERNAME }}"
baseUrlUserPassword: "${{ secrets.NUGET_PASSWORD }}"
isBaseUrlPasswordClearText: "false"
Dependency Filtering
- name: "Generate filtered SBOM"
uses: laerdal/github_actions/dotnet-cyclonedx@main
with:
path: "./src/MyApp.csproj"
exclude-dev: "true"
exclude-test-projects: "true"
exclude-filter: "Microsoft.AspNetCore.App@8.0.0,System.Text.Json@7.0.0"
output-format: "Json"
๐ง Output Format Support
| Format | Description | File Extension | Use Case |
|---|---|---|---|
Auto |
Automatically detects based on filename | .xml or .json |
Default, flexible |
Xml |
CycloneDX XML format | .xml |
Standards compliance |
Json |
CycloneDX JSON format | .json |
API integration |
UnsafeJson |
JSON with relaxed escaping | .json |
Special characters |
๐ฏ Component Types
| Type | Description | Example Use Case |
|---|---|---|
Application |
Standalone application | Web apps, desktop apps |
Library |
Reusable library | NuGet packages, class libraries |
Framework |
Development framework | ASP.NET Core, Entity Framework |
Container |
Container image | Docker containers |
Operating_System |
OS components | Linux distributions |
Device |
Hardware device | IoT devices |
Firmware |
Device firmware | Embedded systems |
๐ Troubleshooting
Common Issues
CycloneDX Tool Not Found
Problem: CycloneDX global tool is not installed
Solution: Ensure global: "true" (default) or install manually:
- name: "Install CycloneDX"
run: dotnet tool install --global CycloneDX
Project File Not Found
Problem: Specified path does not exist
Solution: Verify the path and file existence:
- name: "Check project file"
run: ls -la ./src/MyProject.csproj
GitHub API Rate Limiting
Problem: License resolution fails due to rate limits
Solution: Provide authentication token:
github-bearer-token: "${{ secrets.GITHUB_TOKEN }}"
enable-github-licenses: "true"
Large Project Timeouts
Problem: Command times out on large solutions
Solution: Increase timeout value:
dotnet-command-timeout: "900000" # 15 minutes
Missing Dependencies in SBOM
Problem: Some dependencies not included
Solution: Ensure proper restore and disable selective restore:
disable-package-restore: "false"
recursive: "true"
Debug Tips
- Enable Summary: Set
show-summary: "true"for detailed information - Check Outputs: Use the
sbom-pathoutput to verify file location - Validate Format: Ensure the generated SBOM is valid CycloneDX
- Review Exclusions: Check if dependencies are excluded by filters
๐ Requirements
- GitHub Actions runner (Windows, Linux, or macOS)
- .NET SDK installed (use
actions/setup-dotnet) - Valid .NET project, solution, or packages.config structure
- CycloneDX global tool (auto-installed by default)
๐ Security Considerations
- Token Masking: Sensitive tokens are automatically masked in logs
- Private Repositories: Use appropriate authentication for private NuGet feeds
- License Data: GitHub license resolution requires minimal read permissions
- SBOM Content: Review generated SBOMs before publishing to ensure no sensitive data
๐ SBOM Standards Compliance
This action generates CycloneDX-compliant SBOMs that meet:
- CycloneDX Specification: Follows official CycloneDX schema
- SPDX Compatibility: Can be converted to SPDX format
- NTIA Minimum Elements: Includes required SBOM components
- Supply Chain Security: Supports vulnerability scanning integration
๐ License
This action is part of the GitHub Actions collection by Francois Raminosona.
๐ก Tip: For complete SBOM workflows, combine this action with our signing and publishing actions in the Related Actions section.