The CycloneDX Gradle plugin creates an aggregate of all direct and transitive dependencies of a project and creates a valid CycloneDX SBOM. CycloneDX is a lightweight software bill of materials (SBOM) specification designed for use in application security contexts and supply chain component analysis.
- Features
- Installation
- Quick Start
- Usage
- Configuration
- Tasks
- Examples
- Gradle Support
- CycloneDX Schema Support
- Copyright & License
- âś… Per-Project SBOMs: Generate individual SBOM documents for each project
- âś… Multi-Project Aggregation: Create consolidated SBOMs for entire project hierarchies
- âś… Multiple Output Formats: JSON and XML format support with CycloneDX specification compliance
- âś… Flexible Configuration: Include/exclude specific dependencies, configurations, and projects
- âś… Metadata Enrichment: Include license information, build system details, and organizational data
- âś… Gradle Integration: Native Gradle task integration with proper incremental build support
- âś… Dependency Analysis: Analyzes all direct and transitive resolved dependencies (not just declared ones)
Apply the plugin to your project:
Groovy DSL:
plugins {
id 'org.cyclonedx.bom' version '3.0.0-alpha-0'
}
Kotlin DSL:
plugins {
id("org.cyclonedx.bom") version "3.0.0-alpha-0"
}
Important
Plugin will register aggregate task cyclonedxBom
only in the project where it is applied. This task
aggregates SBOMs from the project and all subprojects in multi-project builds.
Important
Although the plugin is compatible with Java versions starting from 8, support of all versions prior to 17 is deprecated it will be removed in future releases.
- Apply the plugin to your root project
- Run the SBOM generation task:
# Generate per-project SBOMs
./gradlew cyclonedxDirectBom
# Generate aggregated SBOM (for multi-project builds)
./gradlew cyclonedxBom
- Find your SBOM files:
- Per-project:
build/reports/cyclonedx-direct/bom.{json,xml}
- Aggregated:
build/reports/cyclonedx/bom.{json,xml}
- Per-project:
The cyclonedxDirectBom
task generates individual SBOM documents for each project in your build. This is useful when
you want
to analyze dependencies at a granular level.
# Generate SBOMs for all projects
./gradlew cyclonedxDirectBom
# Generate with verbose logging
./gradlew cyclonedxDirectBom --info
# Generate for specific project only
./gradlew :subproject:cyclonedxDirectBom
Output locations:
- JSON:
{project}/build/reports/cyclonedx-direct/bom.json
- XML:
{project}/build/reports/cyclonedx-direct/bom.xml
The cyclonedxBom
task creates a single, consolidated SBOM containing dependencies from all projects in your
build. This provides a complete view of your application's supply chain.
# Generate aggregated SBOM
./gradlew cyclonedxBom
Output locations:
- JSON:
build/reports/cyclonedx/bom.json
- XML:
build/reports/cyclonedx/bom.xml
Configure the plugin using the cyclonedxBom
extension in your root project's build file:
cyclonedxBom {
// Configuration properties
}
Property | Type | Default | Description |
---|---|---|---|
includeConfigs |
List<String> |
[] (all configurations) |
Configurations to include in SBOM generation. Supports regex patterns |
skipConfigs |
List<String> |
[] |
Configurations to exclude from SBOM generation. Supports regex patterns |
skipProjects |
List<String> |
[] |
Project names to exclude from aggregated SBOM generation |
projectType |
String |
"library" |
Type of project ("application" , "library" , "framework" , "container" , etc.) |
schemaVersion |
SchemaVersion |
VERSION_16 |
CycloneDX schema version to use |
includeBomSerialNumber |
boolean |
true |
Include unique BOM serial number |
includeLicenseText |
boolean |
true |
Include full license text in components |
includeMetadataResolution |
boolean |
true |
Include complete metadata resolution for components |
includeBuildSystem |
boolean |
true |
Include build system URL from CI environment |
buildSystemEnvironmentVariable |
String |
- | Custom environment variable for build system URL |
componentVersion |
String |
Project version | Override the main component version |
componentName |
String |
Project name | Override the main component name |
componentGroup |
String |
Project group | Override the main component group |
organizationalEntity |
OrganizationalEntity |
- | Organizational metadata for the project, including name, URLs, and contacts |
externalReferences |
List<ExternalReference> |
Git remote URL | External references for the project, such as documentation or issue trackers |
licenseChoice |
LicenseChoice |
- | License information for the main component |
Configure output files using explicit properties for each task. The plugin supports both JSON and XML formats simultaneously or individually:
allprojects {
tasks.withType<CyclonedxDirectTask> {
// Configure JSON output (default: build/reports/cyclonedx/bom.json)
jsonOutput.set(file("build/reports/cyclonedx/${project.name}-bom.json"))
// Configure XML output (default: build/reports/cyclonedx/bom.xml)
xmlOutput.set(file("build/reports/cyclonedx/${project.name}-bom.xml"))
}
tasks.withType<CyclonedxAggregateTask> {
// Configure JSON output (default: build/reports/cyclonedx-aggregate/bom.json)
jsonOutput.set(file("build/reports/cyclonedx-aggregate/${project.name}-bom.json"))
// Configure XML output (default: build/reports/cyclonedx-aggregate/bom.xml)
xmlOutput.set(file("build/reports/cyclonedx-aggregate/${project.name}-bom.xml"))
}
}
To generate only one format, you can disable the other by unsetting its convention:
tasks.withType<CyclonedxDirectTask> {
// Generate only JSON format
xmlOutput.unsetConvention()
// Or generate only XML format
jsonOutput.unsetConvention()
}
tasks.withType<CyclonedxAggregateTask> {
// Generate only JSON format
xmlOutput.unsetConvention()
// Or generate only XML format
jsonOutput.unsetConvention()
}
cyclonedxBom {
// Include only runtime dependencies
includeConfigs = ["runtimeClasspath", "compileClasspath"]
// Exclude all test-related configurations using regex
skipConfigs = [".*test.*", ".*Test.*"]
// Skip specific projects from aggregation
skipProjects = ["test-utils", "integration-tests"]
// Set application metadata
projectType = "application"
componentName = "my-microservice"
componentVersion = "2.0.0-SNAPSHOT"
// Schema configuration
schemaVersion = org.cyclonedx.model.schema.SchemaVersion.VERSION_16
// Metadata options
includeBomSerialNumber = true
includeLicenseText = true
includeMetadataResolution = true
includeBuildSystem = true
// Custom build system URL template
buildSystemEnvironmentVariable = '${CI_PIPELINE_URL}/jobs/${CI_JOB_ID}'
// Custom output locations
jsonOutput = file("build/reports/sbom/${project.name}-sbom.json")
xmlOutput = file("build/reports/sbom/${project.name}-sbom.xml")
}
Task | Description | Scope | Type | Output Location |
---|---|---|---|---|
cyclonedxDirectBom |
Generates per-project SBOM documents | Individual projects | CyclonedxDirectTask |
build/reports/cyclonedx-direct/ |
cyclonedxBom |
Generates aggregated SBOM for multi-project builds | Entire project hierarchy | CyclonedxAggregateTask |
build/reports/cyclonedx/ |
Both tasks support:
- Incremental builds
- Parallel execution
- Configuration cache
- Build cache
plugins {
id("org.cyclonedx.bom") version "3.0.0-alpha-0"
id("application")
}
cyclonedxBom {
projectType = "application"
includeConfigs = listOf("runtimeClasspath")
}
// Root build.gradle.kts
plugins {
id("org.cyclonedx.bom") version "3.0.0-alpha-0"
}
cyclonedxBom {
// Exclude test and development subprojects
skipProjects = listOf("test-utils", "dev-tools", "benchmarks")
// Include only production dependencies
includeConfigs = listOf("runtimeClasspath", "compileClasspath")
skipConfigs = listOf("testRuntimeClasspath", "testCompileClasspath")
// Application metadata
projectType = "application"
componentGroup = "com.example"
componentName = "my-enterprise-app"
componentVersion = "1.0.0"
// Enable build system tracking
includeBuildSystem = true
}
import org.cyclonedx.model.*
import org.cyclonedx.model.schema.*
plugins {
id("org.cyclonedx.bom") version "3.0.0-alpha-0"
id("java")
}
cyclonedxBom {
// Project configuration
projectType = "application"
schemaVersion = SchemaVersion.VERSION_16
// Component details
componentName = "acme-payment-service"
componentVersion = "3.1.0"
// Dependency filtering
includeConfigs = listOf("runtimeClasspath", "compileClasspath")
skipConfigs = listOf(".*test.*", ".*benchmark.*")
// Metadata options
includeBomSerialNumber = true
includeLicenseText = true
includeMetadataResolution = true
includeBuildSystem = true
buildSystemEnvironmentVariable = "\${BUILD_URL}"
// Organizational metadata
organizationalEntity = OrganizationalEntity().apply {
name = "ACME Corporation"
urls = listOf("https://www.acme.com", "https://security.acme.com")
addContact(OrganizationalContact().apply {
name = "Security Team"
email = "[email protected]"
phone = "+1-555-SECURITY"
})
}
}
import org.cyclonedx.model.*
plugins {
id("org.cyclonedx.bom") version "3.0.0-alpha-0"
id("java")
}
cyclonedxBom {
externalReferences = listOf(
ExternalReference().apply {
url = "https://cyclonedx.org/"
type = ExternalReference.Type.WEBSITE
}
)
}
import org.cyclonedx.model.*
plugins {
id("org.cyclonedx.bom") version "3.0.0-alpha-0"
id("java")
}
cyclonedxBom {
// Specify licenses for the main component
licenseChoice = LicenseChoice().apply {
addLicense(License().apply {
name = "Apache-2.0"
url = "https://www.apache.org/licenses/LICENSE-2.0.txt"
})
}
}
plugins {
id("org.cyclonedx.bom") version "3.0.0-alpha-0"
id("java")
}
cyclonedxBom {
projectType = "application"
// Dynamic versioning for CI/CD
componentVersion = System.getenv("BUILD_VERSION") ?: project.version.toString()
// Build system integration
includeBuildSystem = true
buildSystemEnvironmentVariable = "\${BUILD_URL}"
// Conditional configuration based on environment
if (System.getenv("CI") == "true") {
// CI environment - include all runtime dependencies
includeConfigs = listOf("runtimeClasspath", "compileClasspath")
skipConfigs = listOf("testRuntimeClasspath")
} else {
// Local development - lighter analysis
includeConfigs = listOf("runtimeClasspath")
}
}
tasks.withType<CyclonedxAggregateTask> {
// Timestamped output artifacts (WARNING: will disable Gradle cache)
jsonOutput = file("build/artifacts/sbom-${Instant.now()}.json")
xmlOutput.unsetConvention()
}
For detailed metadata structure information, refer to the CycloneDX specification.
The following table provides information on the version of this Gradle plugin, the Gradle version supported.
Version | Gradle Version |
---|---|
3.0.x | Gradle 8.4+ |
2.x.x | Gradle 8.0+ |
1.x.x | Gradle <8.0 |
The following table provides information on the version of this Gradle plugin, the CycloneDX schema version supported, as well as the output format options. Use the latest possible version of this plugin that is the compatible with the CycloneDX version supported by the target system.
Version | Schema Version | Format(s) |
---|---|---|
3.x.x | CycloneDX v1.6 | XML/JSON |
2.x.x | CycloneDX v1.6 | XML/JSON |
1.10.x | CycloneDX v1.6 | XML/JSON |
1.9.x | CycloneDX v1.6 | XML/JSON |
1.8.x | CycloneDX v1.5 | XML/JSON |
1.7.x | CycloneDX v1.4 | XML/JSON |
1.6.x | CycloneDX v1.4 | XML/JSON |
1.5.x | CycloneDX v1.3 | XML/JSON |
1.4.x | CycloneDX v1.3 | XML/JSON |
1.2.x | CycloneDX v1.2 | XML/JSON |
1.1.x | CycloneDX v1.1 | XML |
1.0x | CycloneDX v1.0 | XML |
CycloneDX Gradle Plugin is Copyright (c) OWASP Foundation. All Rights Reserved.
Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the LICENSE file for the full license.