๐ Generate CycloneDX SBOM Action
Generates Software Bill of Materials (SBOM) using the CycloneDX .NET Global Tool with comprehensive configuration options and validation.
Features
- ๐ Generate industry-standard CycloneDX SBOM files
- ๐ฏ Support for multiple .NET project types and frameworks
- ๐ Multiple output formats (XML, JSON, UnsafeJSON)
- ๐ Advanced dependency analysis and filtering
- ๐ GitHub license resolution integration
- ๐ฆ Custom NuGet repository support
- โ๏ธ Extensive configuration options
- ๐ Detailed analysis and reporting
Usage
Basic Usage - Generate SBOM for Project
- name: Generate SBOM
uses: ./dotnet-cyclonedx
with:
path: './src/MyProject.csproj'
Solution-Level SBOM with Custom Output
- name: Generate solution SBOM
uses: ./dotnet-cyclonedx
with:
path: './MyApp.sln'
output: './artifacts/security'
filename: 'security-sbom.xml'
exclude-dev: 'true'
exclude-test-projects: 'true'
Advanced Usage - JSON Format with GitHub License Resolution
- name: Generate comprehensive SBOM
uses: ./dotnet-cyclonedx
with:
path: './src'
output-format: 'Json'
filename: 'sbom.json'
recursive: 'true'
include-project-references: 'true'
enable-github-licenses: 'true'
github-username: ${{ github.actor }}
github-token: ${{ secrets.GITHUB_TOKEN }}
set-name: 'MyApplication'
set-version: ${{ github.ref_name }}
Enterprise Usage - Custom NuGet Feed with Filtering
- name: Generate enterprise SBOM
uses: ./dotnet-cyclonedx
with:
path: './Enterprise.sln'
framework: 'net8.0'
runtime: 'linux-x64'
nuget-url: 'https://nuget.company.com/v3/index.json'
nuget-username: ${{ secrets.NUGET_USERNAME }}
nuget-password: ${{ secrets.NUGET_PASSWORD }}
exclude-filter: 'TestPackage@1.0.0,LegacyLib@2.1.0'
set-type: 'Application'
dotnet-command-timeout: '600000'
Inputs
Input | Description | Required | Default |
---|---|---|---|
path |
Path to a .sln, .slnf, .slnx, .csproj, .fsproj, .vbproj, .xsproj, or packages.config file or directory | โ Yes | |
framework |
Target framework to use. If not defined, all will be aggregated | โ No | "" |
runtime |
Runtime to use. If not defined, all will be aggregated | โ No | "" |
output |
Directory to write the BOM | โ No | "${{ github.workspace }}/output/sbom" |
filename |
Filename for the BOM | โ No | "sbom.xml" |
output-format |
BOM output format (Auto, Xml, Json, UnsafeJson) | โ No | "Auto" |
exclude-dev |
Exclude development dependencies from the BOM | โ No | "true" |
exclude-test-projects |
Exclude test projects from the BOM | โ No | "true" |
recursive |
Recursively scan project references | โ No | "false" |
include-project-references |
Include project references as components | โ No | "false" |
no-serial-number |
Omit the serial number from the resulting BOM | โ No | "false" |
disable-package-restore |
Disable package restore | โ No | "false" |
disable-hash-computation |
Disable hash computation for packages | โ No | "false" |
set-name |
Override the autogenerated BOM metadata component name | โ No | "" |
set-version |
Override the default BOM metadata component version | โ No | "" |
set-type |
Override the default BOM metadata component type | โ No | "Application" |
dotnet-command-timeout |
dotnet command timeout in milliseconds | โ No | "300000" |
github-username |
GitHub username for license resolution | โ No | "" |
github-token |
GitHub personal access token for license resolution | โ No | "" |
github-bearer-token |
GitHub bearer token for license resolution | โ No | "" |
enable-github-licenses |
Enable GitHub license resolution | โ No | "false" |
nuget-url |
Alternative NuGet repository URL | โ No | "" |
nuget-username |
Alternative NuGet repository username | โ No | "" |
nuget-password |
Alternative NuGet repository password/apikey | โ No | "" |
nuget-password-clear-text |
NuGet repository password is cleartext | โ No | "false" |
base-intermediate-output-path |
Custom build environment folder (if obj folder is relocated) | โ No | "" |
import-metadata-path |
Metadata template path with project specific details | โ No | "" |
exclude-filter |
Comma separated list of dependencies to exclude (name1@version1,name2@version2) | โ No | "" |
cyclonedx-version |
Version of CycloneDX tool to install | โ No | "" |
Outputs
Output | Description |
---|---|
sbom-path |
Full path to the generated SBOM file |
sbom-size |
Size of the generated SBOM file in bytes |
dependencies-count |
Number of dependencies found in the SBOM |
output-format |
Actual output format used |
Component Types
Valid values for set-type
parameter:
Type | Description |
---|---|
Application |
Software application (default) |
Container |
Container image |
Cryptographic_Asset |
Cryptographic asset |
Data |
Data asset |
Device |
Hardware device |
Device_Driver |
Device driver |
File |
File asset |
Firmware |
Firmware |
Framework |
Software framework |
Library |
Software library |
Machine_Learning_Model |
ML model |
Null |
Null component |
Operating_System |
Operating system |
Platform |
Platform |
Output Formats
Format | Description | File Extension |
---|---|---|
Auto |
Automatically determined based on filename | .xml or .json |
Xml |
CycloneDX XML format | .xml |
Json |
CycloneDX JSON format | .json |
UnsafeJson |
CycloneDX JSON format without validation | .json |
Examples
Example 1: CI/CD Pipeline with SBOM Generation
name: Build and Generate SBOM
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Restore dependencies
run: dotnet restore
- name: Build application
run: dotnet build --configuration Release --no-restore
- name: Generate SBOM
uses: ./dotnet-cyclonedx
with:
path: './src/MyApp.csproj'
output: './artifacts/security'
filename: 'sbom.xml'
exclude-dev: 'true'
exclude-test-projects: 'true'
set-name: 'MyApplication'
set-version: ${{ github.sha }}
- name: Upload SBOM artifact
uses: actions/upload-artifact@v4
with:
name: sbom
path: './artifacts/security/sbom.xml'
- name: Validate SBOM
run: |
echo "SBOM generated at: ${{ steps.generate-sbom.outputs.sbom-path }}"
echo "File size: ${{ steps.generate-sbom.outputs.sbom-size }} bytes"
echo "Dependencies: ${{ steps.generate-sbom.outputs.dependencies-count }}"
Example 2: Multi-Framework SBOM Generation
name: Generate Multi-Framework SBOMs
on: [workflow_dispatch]
jobs:
generate-sboms:
runs-on: ubuntu-latest
strategy:
matrix:
framework: ['net6.0', 'net7.0', 'net8.0']
format: ['Xml', 'Json']
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
7.0.x
8.0.x
- name: Generate SBOM for ${{ matrix.framework }}
uses: ./dotnet-cyclonedx
with:
path: './src/MultiTarget.csproj'
framework: ${{ matrix.framework }}
output-format: ${{ matrix.format }}
filename: 'sbom-${{ matrix.framework }}.${{ matrix.format == "Json" && "json" || "xml" }}'
output: './artifacts/sboms'
recursive: 'true'
include-project-references: 'true'
- name: Upload SBOM artifacts
uses: actions/upload-artifact@v4
with:
name: sbom-${{ matrix.framework }}-${{ matrix.format }}
path: './artifacts/sboms/'
Example 3: Enterprise SBOM with License Resolution
name: Enterprise Security Compliance
on:
schedule:
- cron: '0 2 * * 1' # Weekly on Monday
workflow_dispatch:
jobs:
compliance-scan:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Configure enterprise NuGet sources
uses: ./dotnet-nuget-feed-setup
with:
name: 'Enterprise'
source: 'https://nuget.enterprise.com/v3/index.json'
username: ${{ secrets.ENTERPRISE_NUGET_USER }}
password: ${{ secrets.ENTERPRISE_NUGET_TOKEN }}
- name: Generate comprehensive SBOM
uses: ./dotnet-cyclonedx
with:
path: './Enterprise.sln'
output: './compliance/sbom'
filename: 'enterprise-sbom.json'
output-format: 'Json'
recursive: 'true'
include-project-references: 'true'
enable-github-licenses: 'true'
github-username: ${{ github.actor }}
github-token: ${{ secrets.GITHUB_TOKEN }}
nuget-url: 'https://nuget.enterprise.com/v3/index.json'
nuget-username: ${{ secrets.ENTERPRISE_NUGET_USER }}
nuget-password: ${{ secrets.ENTERPRISE_NUGET_TOKEN }}
exclude-filter: 'TestUtilities@1.0.0,MockFramework@2.1.0'
set-name: 'EnterpriseApplication'
set-version: ${{ github.ref_name }}
set-type: 'Application'
dotnet-command-timeout: '900000'
- name: Validate compliance
run: |
echo "๐ SBOM Analysis Results:"
echo "๐ File: ${{ steps.generate-sbom.outputs.sbom-path }}"
echo "๐ Size: ${{ steps.generate-sbom.outputs.sbom-size }} bytes"
echo "๐ฆ Dependencies: ${{ steps.generate-sbom.outputs.dependencies-count }}"
# Validate SBOM structure
jq '.metadata.component.name' ./compliance/sbom/enterprise-sbom.json
jq '.components | length' ./compliance/sbom/enterprise-sbom.json
- name: Upload to compliance system
run: |
# Upload SBOM to enterprise compliance system
curl -X POST \
-H "Authorization: Bearer ${{ secrets.COMPLIANCE_TOKEN }}" \
-H "Content-Type: application/json" \
-d @./compliance/sbom/enterprise-sbom.json \
https://compliance.enterprise.com/api/sbom/upload
Example 4: Container SBOM Generation
name: Container Security Scan
on:
push:
tags: ['v*']
jobs:
container-sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Generate application SBOM
uses: ./dotnet-cyclonedx
with:
path: './src/WebApp.csproj'
output: './docker/security'
filename: 'app-sbom.xml'
exclude-dev: 'true'
exclude-test-projects: 'true'
recursive: 'true'
set-name: 'WebApplication'
set-version: ${{ github.ref_name }}
set-type: 'Container'
- name: Build container image
run: |
docker build -t myapp:${{ github.ref_name }} .
- name: Scan container for vulnerabilities
run: |
# Use SBOM for container security scanning
echo "๐ Scanning container with SBOM data..."
# Integration with security scanning tools
Requirements
- โ
.NET SDK must be installed (use
actions/setup-dotnet
) - โ Valid .NET project or solution file
- โ CycloneDX tool is automatically installed
- โ Network access for NuGet package resolution
- โ GitHub token for license resolution (optional)
Security and Compliance
๐ก๏ธ Security Benefits
- Vulnerability Management: Track all dependencies for security scanning
- License Compliance: Identify license obligations and risks
- Supply Chain Security: Complete visibility into software components
- Audit Trail: Detailed component provenance information
๐ Compliance Standards
- NTIA Minimum Elements: Meets NIST guidelines for SBOM
- SPDX Compatible: Industry-standard format
- CycloneDX Standard: OWASP-endorsed SBOM format
- Executive Order 14028: US government cybersecurity requirements
๐ Best Practices
- Regular Generation: Generate SBOMs for every release
- Version Control: Store SBOMs with source code
- Automated Scanning: Integrate with vulnerability databases
- License Review: Regular license compliance audits
Advanced Configuration
GitHub License Resolution
Enable comprehensive license detection:
- name: Generate SBOM with license data
uses: ./dotnet-cyclonedx
with:
path: './src'
enable-github-licenses: 'true'
github-username: ${{ github.actor }}
github-token: ${{ secrets.GITHUB_TOKEN }}
Custom NuGet Sources
For private package feeds:
- name: Generate SBOM from private feeds
uses: ./dotnet-cyclonedx
with:
path: './src'
nuget-url: 'https://private.nuget.company.com/v3/index.json'
nuget-username: ${{ secrets.PRIVATE_NUGET_USER }}
nuget-password: ${{ secrets.PRIVATE_NUGET_TOKEN }}
nuget-password-clear-text: 'false'
Dependency Filtering
Exclude specific packages:
- name: Generate filtered SBOM
uses: ./dotnet-cyclonedx
with:
path: './src'
exclude-filter: 'TestPackage@1.0.0,DevTool@2.1.0,LegacyLib@3.0.0'
exclude-dev: 'true'
exclude-test-projects: 'true'
Custom Metadata
Override component information:
- name: Generate SBOM with custom metadata
uses: ./dotnet-cyclonedx
with:
path: './src'
set-name: 'ProductionApplication'
set-version: ${{ github.ref_name }}
set-type: 'Application'
import-metadata-path: './metadata/component-info.json'
Output Analysis
SBOM Structure (XML)
<?xml version="1.0" encoding="utf-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" version="1">
<metadata>
<component type="application">
<name>MyApplication</name>
<version>1.0.0</version>
</component>
</metadata>
<components>
<component type="library">
<name>Newtonsoft.Json</name>
<version>13.0.3</version>
<purl>pkg:nuget/Newtonsoft.Json@13.0.3</purl>
</component>
</components>
</bom>
SBOM Structure (JSON)
{
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"version": 1,
"metadata": {
"component": {
"type": "application",
"name": "MyApplication",
"version": "1.0.0"
}
},
"components": [
{
"type": "library",
"name": "Newtonsoft.Json",
"version": "13.0.3",
"purl": "pkg:nuget/Newtonsoft.Json@13.0.3"
}
]
}
Error Handling
The action includes comprehensive error handling:
๐ Validation Errors
- Missing or invalid project files
- Invalid component types or output formats
- Malformed authentication credentials
- Invalid timeout values
๐ฆ Tool Installation Errors
- CycloneDX tool installation failures
- Version compatibility issues
- Network connectivity problems
๐ง Generation Errors
- Project compilation failures
- Package restore issues
- Memory or timeout limitations
- Invalid exclude filters
Troubleshooting
Common Issues
Tool Installation Failed
Failed to install CycloneDX tool
- Solution: Check network connectivity and NuGet access
Project Build Failed
Build failed for project
- Solution: Ensure project builds successfully with
dotnet build
- Solution: Ensure project builds successfully with
Large Memory Usage
OutOfMemoryException during SBOM generation
- Solution: Increase
dotnet-command-timeout
or useexclude-dev: 'true'
- Solution: Increase
Missing Dependencies
Unable to resolve package references
- Solution: Configure proper NuGet sources or disable package restore
Debug Mode
Enable verbose output:
env:
ACTIONS_STEP_DEBUG: true
Performance Tuning
For large solutions:
- name: Generate optimized SBOM
uses: ./dotnet-cyclonedx
with:
path: './Large.sln'
exclude-dev: 'true'
exclude-test-projects: 'true'
disable-hash-computation: 'true'
dotnet-command-timeout: '900000'
Integration with Security Tools
Vulnerability Scanning
- name: Generate SBOM
uses: ./dotnet-cyclonedx
with:
path: './src'
output-format: 'Json'
filename: 'sbom.json'
- name: Scan for vulnerabilities
run: |
# Example with GitHub Advisory Database
npm install -g @cyclonedx/cli
cyclonedx-cli validate --input-file ./output/sbom/sbom.json
License Analysis
- name: Generate SBOM with licenses
uses: ./dotnet-cyclonedx
with:
path: './src'
enable-github-licenses: 'true'
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Analyze licenses
run: |
# Extract license information
jq '.components[].licenses' ./output/sbom/sbom.xml
Version Compatibility
.NET Version | CycloneDX Support |
---|---|
.NET 8.0 | โ Full Support |
.NET 7.0 | โ Full Support |
.NET 6.0 | โ Full Support |
.NET 5.0 | โ Full Support |
.NET Core 3.1 | โ Full Support |
.NET Framework | โ Limited Support |
Contributing
When contributing to this action, please ensure:
- โ Follow the Actions structure principles
- ๐งช Test with various project types and sizes
- ๐ Update documentation for new features
- ๐ Handle sensitive information securely
- ๐ Validate all inputs thoroughly
- ๐ Maintain comprehensive summary reporting
- ๐ก๏ธ Consider security and compliance implications