๐Ÿ“„ 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

  1. Tool Installation Failed

    Failed to install CycloneDX tool
    
    • Solution: Check network connectivity and NuGet access
  2. Project Build Failed

    Build failed for project
    
    • Solution: Ensure project builds successfully with dotnet build
  3. Large Memory Usage

    OutOfMemoryException during SBOM generation
    
    • Solution: Increase dotnet-command-timeout or use exclude-dev: 'true'
  4. 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