Provetry startet im November 2026. Der kostenlose CRA-Check, die Werkzeuge und die Leitfäden sind schon jetzt verfügbar.

SBOM für Java: Maven und Gradle nach dem CRA

7 Min. Lesezeit

Auf dieser Seite
  1. Maven: im Build erzeugen
  2. Gradle: erst sperren, dann erzeugen
  3. Spring Boot erledigt einen Teil für Sie
  4. Was das Build-Werkzeug nicht zeigt
  5. Von der SBOM zu den Schwachstellen
  6. Wie Provetry hilft
  7. Quellen

Der Cyber Resilience Act verlangt von jedem Hersteller eine Software-Stückliste in einem gängigen, maschinenlesbaren Format, die mindestens die Abhängigkeiten der obersten Ebene des Produkts erfasst (Anhang I Teil II Nummer 1). Java hat dabei eine besondere Schwierigkeit: Maven kennt keine Lock-Datei, und nur das Build-Werkzeug kennt den vollständigen Abhängigkeitsbaum, nachdem es Parent-POMs, BOMs und Versionskonflikte aufgelöst hat. Die SBOM muss daher aus dem Build selbst kommen.

Zur Verordnung selbst siehe SBOM für den Cyber Resilience Act.

Maven: im Build erzeugen

Das CycloneDX-Plugin für Maven löst den Abhängigkeitsbaum genau so auf wie Maven und schreibt die SBOM. Sie können es einmal ausführen, ohne die POM anzufassen:

mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom

Oder Sie binden es an die Phase package, damit jeder Build eine erzeugt:

<plugin>
  <groupId>org.cyclonedx</groupId>
  <artifactId>cyclonedx-maven-plugin</artifactId>
  <version>2.9.1</version>
  <executions>
    <execution>
      <phase>package</phase>
      <goals><goal>makeAggregateBom</goal></goals>
    </execution>
  </executions>
</plugin>

makeAggregateBom beschreibt einen Multi-Modul-Build in einer Datei; makeBom schreibt eine pro Modul. Die Dateien landen in target/ (standardmäßig bom.json und bom.xml), und die Versionen 2.9 des Plugins schreiben CycloneDX 1.6. Standardmäßig behält das Plugin die Scopes compile, provided, runtime und system und lässt Testabhängigkeiten weg.

Die pom.xml allein zu lesen genügt nicht. Eine Version, die von einer Parent-POM geerbt oder aus einer BOM wie spring-boot-dependencies importiert wird, liegt außerhalb Ihres Repositorys, und Konflikte zwischen transitiven Versionen entscheidet Maven nach der Regel „nearest wins“. Alles, was die POM als Text liest, übersieht einen Teil des Baums.

Gradle: erst sperren, dann erzeugen

Schalten Sie das Dependency Locking ein, damit die Versionen festliegen und im Repository sichtbar sind:

dependencyLocking {
    lockAllConfigurations()
}

Wenden Sie es in jedem Projekt an (zum Beispiel in allprojects { }). Dann schreibt ./gradlew dependencies --write-locks, in jedem Projekt ausgeführt, eine gradle.lockfile pro Projekt mit jeder aufgelösten Komponente für jede Konfiguration.

Für die SBOM selbst wenden Sie das CycloneDX-Plugin für Gradle an:

plugins {
    id("org.cyclonedx.bom") version "3.4.0"
}

Seit Version 3.0 schreibt ./gradlew cyclonedxDirectBom eine SBOM pro Projekt (in build/reports/cyclonedx-direct/), und ./gradlew cyclonedxBom fasst einen Multi-Projekt-Build zusammen (in build/reports/cyclonedx/). Beschränken Sie es auf das, was ausgeliefert wird, meist runtimeClasspath, mit includeConfigs an der Task cyclonedxDirectBom.

Spring Boot erledigt einen Teil für Sie

Ab Spring Boot 3.3 genügt es, das CycloneDX-Plugin hinzuzufügen: Spring Boot konfiguriert es, legt die SBOM im ausführbaren Jar unter META-INF/sbom/application.cdx.json ab und vermerkt ihren Ort im Manifest des Jars. Die SBOM reist dann mit jeder Kopie des Jars. Der Actuator kann sie außerdem unter /actuator/sbom ausliefern; wenn Sie das einschalten, halten Sie den Endpunkt vom öffentlichen Internet fern, denn der CRA verlangt nicht, dass Sie Ihre SBOM veröffentlichen, und Angreifer kennen gern Ihre Versionen.

Was das Build-Werkzeug nicht zeigt

  • Fat- und Shaded-Jars. Ein Shaded-Jar kopiert Klassen anderer Bibliotheken in Ihr eigenes, manchmal unter einem neuen Paketnamen. Log4Shell (CVE-2021-44228) hat den Preis gezeigt: Viele Teams wussten nicht, dass log4j-core in einem Jar steckte, das sie auslieferten. Erzeugen Sie die SBOM aus dem Build, der das Jar erzeugt, und prüfen Sie, was Sie hineinshaden.
  • Die Java-Laufzeitumgebung. Wenn Sie mit dem Produkt eine JRE ausliefern (ein jlink-Image, einen Installer, ein Container-Image), ist ihre Version eine Komponente, mit vierteljährlichen Sicherheitsupdates von Oracle und den OpenJDK-Distributoren.
  • Anwendungsserver und Agenten. Ein WAR auf einem Tomcat, den Sie mitliefern, oder ein APM-Agent, der beim Start hinzugefügt wird, gehört ebenfalls zum Produkt.

Von der SBOM zu den Schwachstellen

Die Plugins listen nur Komponenten auf; ein Scanner wie OWASP Dependency-Check oder jedes Werkzeug, das CycloneDX liest, gleicht sie mit Sicherheitshinweisen ab. Schauen Sie zuerst auf die in freier Wildbahn ausgenutzten Schwachstellen, die die Meldeuhr starten können, und halten Sie in einer VEX-Aussage fest, warum eine verwundbare Klasse, die Ihr Code nie lädt, das Produkt nicht betrifft.

Wie Provetry hilft

Die zuverlässigste Eingabe ist die SBOM, die das CycloneDX-Plugin für Maven oder Gradle schreibt: Laden Sie sie hoch oder senden Sie sie aus Ihrer CI, und Provetry bewahrt sie mit der Version auf, schreibt sie in den kostenpflichtigen Tarifen auch in SPDX und überwacht jede Komponente auf neue und ausgenutzte Schwachstellen, täglich in den kostenpflichtigen Tarifen und wöchentlich im kostenlosen. Es liest auch gradle.lockfile-Dateien direkt und behandelt Test-, Compile-only- und Annotation-Processor-Konfigurationen als Entwicklungsabhängigkeiten. Aus einer bloßen pom.xml liest es nur die direkten Abhängigkeiten, die es innerhalb Ihres Repositorys auflösen kann, sagt, welche Versionen es nicht auflösen konnte, und kennzeichnet die SBOM als unvollständig, statt zu raten. Es zeigt, wo Ihr Code ein verwundbares Paket importiert, mit Datei und Zeile, schließt aber nie, dass ein Java-Paket ungenutzt ist: Ohne vollständigen Abhängigkeitsgraphen kann es das nicht ausschließen.

Quellen