CRA Desk
Every generate step

Generating an SBOM for Java / Kotlin (Gradle)

The step below writes a CycloneDX JSON software bill of materials (SBOM) in your own pipeline. The CRA Desk scan reads that file and turns it into a Cyber Resilience Act (CRA) readiness report - it never generates one for you.

Add to build.gradle:

plugins {
  id 'org.cyclonedx.bom' version '1.10.0'
}

Run in CI:

./gradlew cyclonedxBom
Produces:
build/reports/bom.json
Format:
CycloneDX JSON
Generator documentation

What the generator actually reads

The task resolves the configurations of the project it is applied to and reports the outcome of that resolution. Dynamic versions (1.+, latest.release) and version-catalog aliases are therefore already collapsed to concrete versions in the output: the file records what this build resolved, which is not necessarily what the next build would.

Versions and package URLs

Gradle publishes to Maven coordinates, so components arrive as pkg:maven purls and match OSV's Maven advisories. A dependency rewritten by a resolution rule appears under the coordinates it was substituted to - the correct answer for a vulnerability match and a surprising one if you were reading build.gradle instead.

The whole CI job

GitHub Actions

- uses: actions/checkout@v4
- run: ./gradlew cyclonedxBom
- uses: mmalinowski/cradesk-action@v1
  with:
    sbom-path: build/reports/bom.json

GitLab CI/CD

generate-sbom:
  script:
    - ./gradlew cyclonedxBom

include:
  - component: gitlab.com/cradesk/scan/readiness@1
    inputs:
      sbom_path: build/reports/bom.json

Only the first step changes with your stack - the CRA Desk step after it is identical everywhere.

What goes wrong here

The plugin writes into the module that applies it, so in a multi-project build apply it to the root project or point sbom-path at the module you actually ship.

Repositories with more than one thing in them

The file lands under the build directory of whichever project produced it, so the question in a build with several projects is not only where the plugin is applied but which of the resulting files describes the artefact you ship. Compare the component count against a dependency listing before pointing the scan at one - a BOM covering the root project's own configurations can be a fraction of the real graph.

What CRA Desk does with the result

Components from this build carry pkg:maven package URLs, which the watch matches against OSV's Maven advisories when the SBOM arrives and again as new advisories land. Matching runs on every plan; e-mail alerts and the full match list are what a paid plan adds.

A generator that runs is not the same as coverage. Components with no purl, no version, or from an ecosystem outside the ones we watch are counted as gaps in every report rather than reported as clean.

Other stacks