CycloneDX.MSBuild
1.3.1
dotnet add package CycloneDX.MSBuild --version 1.3.1
NuGet\Install-Package CycloneDX.MSBuild -Version 1.3.1
<PackageReference Include="CycloneDX.MSBuild" Version="1.3.1"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="CycloneDX.MSBuild" Version="1.3.1" />
<PackageReference Include="CycloneDX.MSBuild"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add CycloneDX.MSBuild --version 1.3.1
#r "nuget: CycloneDX.MSBuild, 1.3.1"
#:package CycloneDX.MSBuild@1.3.1
#addin nuget:?package=CycloneDX.MSBuild&version=1.3.1
#tool nuget:?package=CycloneDX.MSBuild&version=1.3.1
CycloneDX.MSBuild
MSBuild targets for automatic CycloneDX SBOM (Software Bill of Materials) generation during build and pack operations. Seamlessly integrates the CycloneDX .NET tool into your build pipeline.
๐ฏ Overview
CycloneDX.MSBuild is a NuGet package inspired by Microsoft.Sbom.Targets that automatically generates CycloneDX SBOMs for your .NET projects. Simply add the package reference, and SBOMs are generated automatically during dotnet build or dotnet pack.
Why CycloneDX.MSBuild?
- โ Zero Configuration: Works out of the box with sensible defaults
- โ Security by Design: Runs in build context, no elevated permissions required
- โ Multi-Target Support: Handles projects with multiple target frameworks
- โ Flexible: Highly configurable via MSBuild properties
- โ Standards Compliant: Generates CycloneDX 1.2-1.6 compatible SBOMs
- โ Development Dependency: Doesn't pollute your dependency tree
๐ Quick Start
Installation
Add the package to your project:
dotnet add package CycloneDX.MSBuild
Or add it manually to your .csproj:
<ItemGroup>
<PackageReference Include="CycloneDX.MSBuild" Version="1.0.0" PrivateAssets="all" />
</ItemGroup>
Build Your Project
dotnet build
That's it! Your SBOM will be generated at bin/Debug/net8.0/sbom.json (or your output directory).
๐ Features
Automatic SBOM Generation
SBOMs are generated automatically:
- During Build: After successful compilation
- During Pack: Included in NuGet packages under
/sbom/ - During Publish: Copied to the publish directory
- Multi-Targeting: Generates once per project, not per framework
Supported Output Formats
- JSON (default) - CycloneDX JSON format
- XML - CycloneDX XML format
CycloneDX Specification Versions
The tool automatically uses the latest CycloneDX specification version supported by the installed tool version (typically 1.6).
โ๏ธ Configuration
All configuration is done via MSBuild properties. Set them in your .csproj, Directory.Build.props, or command line.
Core Settings
Enable/Disable SBOM Generation
<PropertyGroup>
<GenerateCycloneDxSbom>false</GenerateCycloneDxSbom>
</PropertyGroup>
Error Handling
<PropertyGroup>
<CycloneDxContinueOnError>false</CycloneDxContinueOnError>
</PropertyGroup>
Output Configuration
Output Format
<PropertyGroup>
<CycloneDxOutputFormat>xml</CycloneDxOutputFormat>
</PropertyGroup>
Output Location
<PropertyGroup>
<CycloneDxOutputDirectory>$(MSBuildProjectDirectory)/sbom/</CycloneDxOutputDirectory>
<CycloneDxOutputFilename>software-bom</CycloneDxOutputFilename>
</PropertyGroup>
Advanced Options
Exclude Dependencies
<PropertyGroup>
<CycloneDxExcludeDev>true</CycloneDxExcludeDev>
<CycloneDxExcludeTestProjects>true</CycloneDxExcludeTestProjects>
</PropertyGroup>
Serial Number Control
<PropertyGroup>
<CycloneDxDisableSerialNumber>true</CycloneDxDisableSerialNumber>
</PropertyGroup>
Automatic Metadata Generation
New in v1.1.0: CycloneDX.MSBuild now automatically extracts assembly and package metadata from your project properties and includes it in the generated SBOM. This eliminates the need for manual metadata templates in most cases.
Automatically Extracted Metadata:
- Version: From
Version,VersionPrefix,AssemblyVersion, or GitVersion properties (GitVersion_FullSemVer,GitVersion_SemVer) - Component Name: From
AssemblyNameor project name - Authors/Supplier: From
AuthorsorCompanyproperties - Description: From
DescriptionorPackageDescriptionproperties - Copyright: From
Copyrightproperty - License: From
PackageLicenseExpressionproperty - Package URL (purl): Automatically generated as
pkg:nuget/{name}@{version}
Example Project Configuration:
<PropertyGroup>
<Version>1.2.3</Version>
<Authors>Your Name</Authors>
<Company>Your Company Inc.</Company>
<Description>A brief description of your application</Description>
<Copyright>Copyright (c) 2024 Your Company Inc.</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
Generated SBOM Component Metadata:
{
"component": {
"type": "application",
"bom-ref": "pkg:nuget/YourProject@1.2.3",
"name": "YourProject",
"version": "1.2.3",
"description": "A brief description of your application",
"supplier": {
"name": "Your Name"
},
"copyright": "Copyright (c) 2024 Your Company Inc.",
"licenses": [
{
"license": {
"id": "MIT"
}
}
],
"purl": "pkg:nuget/YourProject@1.2.3"
}
}
Disable Automatic Metadata Generation:
If you prefer to use a manual metadata template or disable metadata generation entirely:
<PropertyGroup>
<CycloneDxGenerateMetadata>false</CycloneDxGenerateMetadata>
</PropertyGroup>
GitVersion Integration:
If you're using GitVersion for semantic versioning, CycloneDX.MSBuild automatically detects and uses the GitVersion-generated version:
Import Metadata Template (Advanced)
Note: With automatic metadata generation enabled by default (see above), manual metadata templates are typically only needed for advanced scenarios or custom metadata structures.
<PropertyGroup>
<CycloneDxImportMetadataPath>$(MSBuildProjectDirectory)/sbom-metadata.xml</CycloneDxImportMetadataPath>
</PropertyGroup>
When you specify a custom metadata template path, automatic metadata generation is skipped, and your template is used instead. This is useful for:
- Adding custom component information beyond standard properties
- Including additional metadata fields not extracted automatically
- Providing complex metadata structures
Example sbom-metadata.xml:
Note: CycloneDX.MSBuild supports metadata templates using CycloneDX schema versions 1.2 through 1.6. You may use any supported version, but 1.6 is recommended for new projects.
<?xml version="1.0" encoding="utf-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.6">
<metadata>
<component type="application" bom-ref="pkg:nuget/YourProject@1.0.0">
<name>YourProject</name>
<version>1.0.0</version>
<description>
<![CDATA[Your project description]]>
</description>
<licenses>
<license>
<name>Apache License 2.0</name>
<id>Apache-2.0</id>
</license>
</licenses>
<purl>pkg:nuget/YourProject@1.0.0</purl>
</component>
</metadata>
</bom>
GitHub License Resolution
<PropertyGroup>
<CycloneDxEnableGitHubLicenses>true</CycloneDxEnableGitHubLicenses>
<CycloneDxGitHubUsername>your-username</CycloneDxGitHubUsername>
<CycloneDxGitHubToken>ghp_yourtoken</CycloneDxGitHubToken>
</PropertyGroup>
Tool Version
<PropertyGroup>
<CycloneDxToolVersion>5.5.0</CycloneDxToolVersion>
</PropertyGroup>
๐ฆ NuGet Package Integration
When you run dotnet pack, the generated SBOM is automatically included in the NuGet package under the /sbom/ directory.
dotnet pack
Consumers of your NuGet package can inspect the SBOM:
# Extract and view
unzip -q MyPackage.1.0.0.nupkg -d extracted
cat extracted/sbom/sbom.json
๐ Publish Integration
When you run dotnet publish, the generated SBOM is automatically copied to the publish directory alongside your application.
dotnet publish -c Release
The SBOM will be available in your publish directory:
# View the SBOM in publish directory
cat bin/Release/net8.0/publish/sbom.json
This makes it easy to include the SBOM when deploying your application, ensuring supply chain transparency in production environments.
๐๏ธ Architecture
MSBuild Integration
CycloneDX.MSBuild uses MSBuild's extensibility hooks:
.propsfile - Defines configurable properties with defaults.targetsfile - Implements build targets for SBOM generationbuildMultiTargeting/- Special handling for multi-target projects
Target Execution Order
Build โ ValidateCycloneDxConfiguration โ EnsureCycloneDxToolInstalled โ GenerateCycloneDxSbom
Security by Design
- Sandboxed Execution: Runs in build context without elevated privileges
- Input Validation: All properties are validated before use
- Fail-Safe Defaults: Continues build on errors by default
- No Code Execution: Only executes vetted CycloneDX tool
- Dependency Pinning: Explicit tool version control
Clean Code Principles
- Separation of Concerns: Configuration (
.props) separated from logic (.targets) - Single Responsibility: Each target has one clear purpose
- DRY: Reusable property groups
- Consistent Naming:
CycloneDx*prefix for all properties - Comprehensive Documentation: XML comments for all properties
๐งช Testing
The repository includes integration tests for various scenarios:
tests/
โโโ SimpleProject/ # Basic single-target project
โโโ MultiTargetProject/ # Multi-targeting (.NET 6, 8, Standard 2.0)
โโโ DisabledProject/ # Project with SBOM generation disabled
๐ Versioning
This project uses automated semantic versioning with:
- MinVer: Automatic version calculation from Git tags
- semantic-release: Automated releases, changelogs, and NuGet publishing
All commits must follow Conventional Commits format.
๐ For detailed information, see VERSIONING.md
๐ CI/CD Pipeline
This project includes a comprehensive CI/CD pipeline with automated testing and publishing:
Continuous Integration (CI)
Runs on all pull requests and feature branches:
- โ Multi-platform testing (Ubuntu, Windows, macOS)
- โ Multi-version .NET testing (.NET 6.0 and 8.0)
- โ Code quality checks (formatting, package validation)
- โ Dependency security scanning (vulnerable and deprecated packages)
- โ Build artifact generation
Continuous Deployment (CD)
Runs on pushes to main, master, beta, or alpha branches:
- Build & Test - Full test suite execution
- Package Validation - NuGet package quality checks
- Semantic Release - Automatic version determination from commits
- NuGet Publishing - Automatic publishing to NuGet.org
- GitHub Release - Automated release notes and changelog
Setting up Automated Publishing
To enable automated NuGet publishing:
- Get a NuGet API key from NuGet.org
- Add it as a GitHub secret named
NUGET_API_KEY - The release workflow will automatically publish on version bumps
๐ For detailed CI/CD documentation, see .github/workflows/README.md
๐ง Development
Project Structure
CycloneDX.MSBuild/
โโโ src/
โ โโโ CycloneDX.MSBuild/
โ โโโ build/
โ โ โโโ CycloneDX.MSBuild.props # Configuration properties
โ โ โโโ CycloneDX.MSBuild.targets # Build integration
โ โโโ buildMultiTargeting/ # Multi-target support
โ โโโ CycloneDX.MSBuild.csproj # Package definition
โโโ tests/
โ โโโ Integration.Tests/
โโโ README.md
Building Locally
# Build the package
dotnet build src/CycloneDX.MSBuild/CycloneDX.MSBuild.csproj
# Pack the package
dotnet pack src/CycloneDX.MSBuild/CycloneDX.MSBuild.csproj
# Test with local projects
dotnet build tests/Integration.Tests/SimpleProject/SimpleProject.csproj
๐ Comparison with Microsoft.Sbom.Targets
| Feature | Microsoft.Sbom.Targets | CycloneDX.MSBuild |
|---|---|---|
| SBOM Format | SPDX 2.2 | CycloneDX 1.2-1.6 |
| Tool | Microsoft.Sbom.Tool (embedded) | CycloneDX .NET tool (local tool, installed on demand) |
| Build Support | โ | โ |
| Pack Support | โ | โ |
| Publish Support | โ | โ |
| Multi-Targeting | โ | โ |
| Development Dependency | โ | โ |
๐ Troubleshooting
Common Issues and Solutions
SBOM Not Generated
Problem: SBOM file is not created after build.
Solutions:
Check if generation is enabled:
dotnet build -p:GenerateCycloneDxSbom=true -v:detailedLook for "GenerateCycloneDxSbom" messages in the output.
Verify the package is installed:
dotnet list package | grep CycloneDX.MSBuildCheck for multi-target projects: For projects with multiple target frameworks, the SBOM is only generated once at the outer build level. Check the project root or custom output directory.
Look in the correct location: Default is
bin/[Configuration]/[TargetFramework]/sbom.json. Check yourCycloneDxOutputDirectorysetting if customized.Check build verbosity: Run with detailed verbosity to see what's happening:
dotnet build -v:detailed 2>&1 | grep -i cyclonedx
Tool Installation Failures
Problem: CycloneDX tool fails to install or is not found.
Solutions:
Manually install the tool:
dotnet tool install --local CycloneDX --version 5.5.0Clear tool cache and retry:
dotnet tool uninstall --local CycloneDX dotnet buildCheck network connectivity: Tool installation requires internet access to download from NuGet.org.
Verify .NET SDK version: Ensure you have .NET SDK 6.0 or later installed:
dotnet --versionCheck for proxy/firewall issues: If behind a corporate proxy, configure NuGet:
dotnet nuget update source nuget.org --http-proxy http://proxy.company.com:8080
GitHub License Resolution Issues
Problem: GitHub API rate limiting or authentication errors.
Solutions:
Rate limiting (60 requests/hour without auth):
- Use GitHub token for higher limits (5000 requests/hour)
- Set
CycloneDxGitHubUsernameandCycloneDxGitHubTokenproperties
Generate a GitHub token:
- Go to GitHub Settings โ Developer settings โ Personal access tokens
- Create token with
public_reposcope (read-only) - Store securely (use environment variables, not source control)
Use environment variables in CI/CD:
dotnet build -p:CycloneDxGitHubToken=$GITHUB_TOKENDisable if not needed:
<CycloneDxEnableGitHubLicenses>false</CycloneDxEnableGitHubLicenses>
Build Performance Issues
Problem: Build time significantly increased after adding CycloneDX.MSBuild.
Solutions:
Disable for Debug builds (only generate for Release):
<PropertyGroup Condition="'$(Configuration)' == 'Debug'"> <GenerateCycloneDxSbom>false</GenerateCycloneDxSbom> </PropertyGroup>Use custom output directory to avoid file locking issues:
<CycloneDxOutputDirectory>$(MSBuildProjectDirectory)/sbom/</CycloneDxOutputDirectory>Exclude test projects from SBOM generation:
<PropertyGroup Condition="$(MSBuildProjectName.EndsWith('.Tests'))"> <GenerateCycloneDxSbom>false</GenerateCycloneDxSbom> </PropertyGroup>Pin tool version to avoid repeated downloads:
<CycloneDxToolVersion>5.5.0</CycloneDxToolVersion>
Multi-Target Framework Issues
Problem: Multiple SBOMs generated or wrong output location for multi-target projects.
Solution: This is expected behavior. CycloneDX.MSBuild automatically detects multi-target projects and generates a single SBOM at the outer build level. If you're seeing multiple SBOMs, check:
Verify buildMultiTargeting files are imported: The package should automatically handle this.
Check output location: SBOM should be in the project directory or custom output directory, not in individual target framework folders.
Clean and rebuild:
dotnet clean dotnet build
SBOM Contains Wrong Information
Problem: SBOM has incorrect dependencies, versions, or metadata.
Solutions:
Ensure dependencies are restored:
dotnet restore dotnet buildCheck for package version conflicts: Look at the build output for version resolution messages.
Use metadata template to override project information:
<CycloneDxImportMetadataPath>sbom-metadata.xml</CycloneDxImportMetadataPath>Verify tool version: Ensure you're using a recent version of the CycloneDX tool:
<CycloneDxToolVersion>5.5.0</CycloneDxToolVersion>Clean package cache and rebuild:
dotnet nuget locals all --clear dotnet restore dotnet build
CI/CD Pipeline Issues
Problem: SBOM generation works locally but fails in CI/CD.
Solutions:
Ensure .NET SDK is available: CI environment must have .NET SDK 6.0+ installed.
Check for file permissions: CI systems may have restricted file access. Use:
dotnet build -p:CycloneDxContinueOnError=trueNetwork access required: Tool installation needs internet access to NuGet.org.
Use explicit restore:
dotnet restore dotnet tool restore dotnet buildCache the tool in CI to improve performance:
# GitHub Actions example - uses: actions/cache@v3 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
XML/JSON Format Issues
Problem: Generated SBOM has parsing errors or invalid format.
Solutions:
Validate the SBOM: Use CycloneDX validation tools:
# Install validator npm install -g @cyclonedx/cyclonedx-cli # Validate SBOM cyclonedx validate --input-file sbom.jsonCheck tool version: Older versions may have bugs. Update to latest:
<CycloneDxToolVersion>5.5.0</CycloneDxToolVersion>Try different format: Switch between JSON and XML to isolate issues:
<CycloneDxOutputFormat>xml</CycloneDxOutputFormat>Check for special characters: Ensure project/package names don't have invalid XML/JSON characters.
Debugging Tips
Enable Detailed Logging
dotnet build -v:detailed > build.log 2>&1
grep -i cyclonedx build.log
Check Tool Installation
dotnet tool list --local
Should show:
Package Id Version Commands
--------------------------------------------------------
CycloneDX 5.5.0 dotnet-CycloneDX
Verify MSBuild Targets Are Loaded
dotnet build -v:diagnostic 2>&1 | grep "CycloneDX.MSBuild.targets"
Should show the targets file being imported.
Test with Minimal Project
Create a simple test project:
dotnet new console -n TestSbom
cd TestSbom
dotnet add package CycloneDX.MSBuild
dotnet build
ls bin/Debug/net8.0/sbom.json
FAQ
Q: Does SBOM generation require internet access? A: Yes, the first build requires internet to download the CycloneDX tool from NuGet.org. Subsequent builds use the cached tool. GitHub license resolution (if enabled) also requires internet access.
Q: Can I use this with .NET Framework projects? A: The package targets netstandard2.0, so it works with .NET Framework 4.6.1+ and all versions of .NET Core/.NET 5+. However, you need .NET SDK 6.0+ installed to run the CycloneDX tool.
Q: Does this work with mono or alternative .NET implementations? A: The package should work with any MSBuild-compatible build system that supports .NET tools.
Q: How do I exclude the SBOM from version control?
A: Add to .gitignore:
# CycloneDX SBOM files
**/bin/**/sbom.json
**/bin/**/sbom.xml
sbom/
Q: Can I validate the SBOM automatically during build? A: Not built-in yet, but you can add a custom MSBuild target that runs validation after SBOM generation. This is a planned feature.
Q: Does the SBOM include transitive dependencies? A: Yes, the CycloneDX tool includes all transitive dependencies by default.
Q: How do I report security vulnerabilities? A: See SECURITY.md for our security policy and reporting process.
Q: What's the performance impact? A: SBOM generation typically adds 2-5 seconds to build time, depending on project size and number of dependencies. Consider disabling for Debug builds if needed.
Getting Help
If you're still experiencing issues:
- Check existing issues: GitHub Issues
- Review CycloneDX tool docs: cyclonedx-dotnet
- Ask in discussions: GitHub Discussions
- File a bug report: Include build logs, project configuration, and environment details
๐ค Contributing
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests.
Guidelines
- Follow existing code style and architecture
- Maintain security by design principles
- Add tests for new features
- Update documentation
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Related Projects
- CycloneDX .NET Tool - The underlying SBOM generation tool
- CycloneDX Specification - CycloneDX standard
- Microsoft.Sbom.Targets - Microsoft's SPDX SBOM tool
- OWASP Dependency-Track - SBOM analysis platform
๐ Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- CycloneDX Community: https://cyclonedx.org/
Made with โค๏ธ for Software Supply Chain Security
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Initial release:
- Automatic SBOM generation during build
- Support for dotnet build and dotnet pack
- Configurable output format (JSON/XML)
- Integration with CycloneDX .NET tool