Safeguard
Developer Tools•

How do you generate a CycloneDX SBOM from a Gradle build?

Apply the CycloneDX Gradle plugin to the root project and run the cyclonedxBom task. Requirements, outputs, direct versus aggregate SBOMs and checks.

Safeguard Security Team
4 min read

Apply the org.cyclonedx.bom plugin to the root project and run the cyclonedxBom task. Gradle then writes a direct SBOM for each project and one aggregate SBOM for the build, as JSON and XML by default, built from the dependency graph Gradle actually resolved.

What is special about the Gradle plugin

The plugin's documentation says it generates CycloneDX documents from Gradle's resolved dependency graphs. It records the components and relationships Gradle selected after conflict resolution, substitution, constraints and transitive resolution. That matters: your SBOM reflects the versions you really shipped, including any constraint you added to force a patch.

Requirements

The readme lists, for the 3.x plugin line, Gradle 8.4 or newer and a build JVM of Java 8 or newer, with support for versions before Java 17 deprecated. The default schema is CycloneDX 1.6, and 1.7 can be selected with the schemaVersion setting. Check the readme for the release you install, since the page warns it documents the current branch.

Steps

  1. Apply the plugin in the root build file.
plugins {
    id("org.cyclonedx.bom") version "3.5.1"
}

The version above is the one shown in the readme at the time of writing. Use the current release.

  1. Generate the aggregate SBOM.
./gradlew cyclonedxBom
  1. Collect the outputs. By default the aggregate lands in build/reports/cyclonedx, and the root project's direct SBOM in build/reports/cyclonedx-direct. Each subproject writes its own direct SBOM in its own build directory.
  2. Store the aggregate with your release artifact.
  3. Wire the task into CI so it runs on every release build.

Direct versus aggregate

TypeCoversUse it for
Direct SBOMOne project's own resolved dependenciesPer service records
Aggregate SBOMThe enabled direct SBOMs combinedA single release record for a multi project build

The plugin supports configuration cache, parallel execution, up to date checks and the build cache, so it should not slow a modern build much.

Choose the configurations carefully

The documentation has a section on selecting configurations. By default you want what ships, which is the runtime classpath, rather than test only libraries. Decide this on purpose and write it down, because a buyer reading your SBOM will assume it describes the shipped product.

You can also exclude a project from aggregation, set component and organizational metadata, and add a CI build reference. The readme has a recipe on using SBOMs with SLSA provenance too.

Checks before you share

  1. Compare a handful of components to the dependencyInsight output.
  2. Confirm the SBOM lists the patched version if you applied a constraint. See how to force a patched transitive dependency in Gradle.
  3. Validate against the declared schema.
  4. Keep one SBOM per released version, not one that gets overwritten.

Try it yourself

Click through it at your own pace, or open it full screen. Compare the grouping of components with what an aggregate SBOM would give you.

Safeguard can ingest SBOMs, scan the dependencies behind them and apply reachability analysis, with policy gates for pull requests. Free scan: gold.safeguard.sh/scan.

Quick check

Does the plugin work with Kotlin DSL builds?

Yes. The readme shows both Kotlin DSL and Groovy DSL examples for applying it.

Why does the SBOM show a different version than my build file?

Because it records what Gradle resolved after conflict resolution and constraints, which can differ from what you declared.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.