
Ein praxisnaher Leitfaden zur Erstellung von CycloneDX-SBOMs mit cdxgen für Node, Python, Java, Go, C/C++ und Container – und was über die erste SBOM-Erstellung hinaus zu tun ist.
Hinweis: Dieser Leitfaden wurde Mitte Juli 2026 gegen die zu diesem Zeitpunkt aktuellen cdxgen-Releases gegengeprüft. cdxgen wird aktiv weiterentwickelt; spätere Releases können Funktionen ergänzen, Fehler beheben oder das Verhalten ändern. Prüfen Sie die offizielle cdxgen-Dokumentation auf die aktuellen Flags und Befehle, bevor Sie sich auf eines der folgenden Beispiele verlassen.
OWASP cdxgen ist der schnellste Weg, eine Codebasis in eine CycloneDX-SBOM zu verwandeln. Es ist der offizielle Generator im CycloneDX-Ökosystem.
cdxgen deckt die meisten modernen Sprachen ab und erzeugt mit einem einzigen Befehl eine gültige SBOM. Wenn Ihr Ziel heute lautet „Beschaff mir eine SBOM", ist dies das Tool, auf das Sie sich verlassen können.
Dieser Leitfaden hilft Ihnen, Ihre erste SBOM zu erstellen, optionale Details aufzunehmen und die SBOM-Erstellung in Pipelines zu operationalisieren. Anschließend zieht er eine Grenze, die die meisten SBOM-Inhalte auslassen. Die Datei zu erzeugen ist der eine Schritt. Sie danach zu nutzen ein anderer. Zu wissen, wo das eine endet und das andere beginnt, erspart Ihnen später eine falsche Annahme.
cdxgen installieren
Drei Wege, cdxgen zu installieren:
Eine Voraussetzung bringt viele zu Fall. C, C++ und Python benötigen Java 21 oder neuer auf dem Rechner. Unter Java 8 oder 11 bleibt cdxgen hängen. Installieren Sie ein aktuelles JDK und setzen Sie zuerst JAVA_HOME, sonst stockt der Lauf ohne erkennbaren Grund.
Erste SBOM erstellen
Wechseln Sie in das Projektverzeichnis und führen Sie einen Befehl aus.
Das erzeugt eine CycloneDX-Datei, bom.json. cdxgen erkennt den Projekttyp automatisch und trifft es meist richtig. Wenn es danebenliegt, ist die Ausgabe dünn oder falsch. Benennen Sie den Typ von Tag eins an explizit mit -t.
Bei einem Repository mit mehreren Services scannen Sie rekursiv. cdxgen fügt alles zu einer aggregierten BOM zusammen.
Legen Sie die Spezifikationsversion bewusst fest. Die Version, die Sie ausgeben, ist die Version, an der Kunden und Regulierungsbehörden Sie messen.
Abdeckung der Ökosysteme
cdxgen punktet mit Breite. Ein einziges Tool ersetzt eine Schublade voll sprachspezifischer Plugins. Die gängigen Aufrufe:
Python: cdxgen -t python. Liest Requirements-Dateien, Poetry und PDM. Benötigt Java 21.
Java / Maven / Gradle: cdxgen -t java. Löst den vollständigen Baum auf, nicht nur die direkten Deklarationen.
Node / npm: cdxgen -t javascript. Durchläuft die Lockfile für den echten transitiven Graphen.
Go: cdxgen -t go.
C / C++: cdxgen -t c. Java 21 erforderlich. Beste Ergebnisse aus einem echten Build, nicht aus einem bloßen Quellbaum.
Container: cdxgen -t docker alpine:3.20 -o bom.json. Zieht OS-Pakete und Sprachabhängigkeiten aus dem Image.
Sie binden das in die CI ein? Prüfen Sie Ihr Ökosystem zuerst gegen die Liste der unterstützten Projekttypen (Supported Project Types). Die Abdeckung ist breit, nicht universell. Besser, eine Lücke zu finden, bevor eine Pipeline davon abhängt.
Nachweis der Komponentennutzung aufnehmen
Eine einfache SBOM listet, was Ihre Manifeste deklarieren. Das ist eine Behauptung. Nachweise (Evidence) sind der Beweis. Für eine regulierte Einreichung zählt dieser Unterschied.
Das Flag --evidence (cdxgen 9.9 und neuer) hält fest, wo jede Komponente verwendet wird – nicht nur, was ein Manifest deklariert hat. Gehen Sie mit Call-Stack-Nachweisen weiter. Sie zeigen, ob eine anfällige Funktion von Ihrem Code aus erreichbar ist.
Erreichbarkeit (Reachability) macht sich bezahlt. Die meisten Scanner melden jede anfällige Abhängigkeit. Viele liegen in Codepfaden, die Sie nie aufrufen. Call-Stack-Nachweise zeigen, welche Befunde Ihren Code tatsächlich berühren. Das ist der Unterschied zwischen einer Triage-Warteschlange von vierhundert und einer von zwölf.
SBOM signieren
Eine unsignierte SBOM ist eine Textdatei, die jeder bearbeiten kann. Geht sie an einen Kunden oder eine Behörde? Signieren Sie sie.
Das erzeugt ein Schlüsselpaar und hängt eine Signatur an. Nachgelagert bestätigt cdx-verify, dass die Datei seit dem Signieren unverändert ist. Verwenden Sie im Produktivbetrieb Ihre eigenen verwalteten Schlüssel, nicht ein generiertes Testpaar. Der Mechanismus ist eingebaut. Schalten Sie ihn früh ein.
In der CI aufsetzen: GitHub Actions, Azure DevOps
GitHub Actions
Nichts davon hilft, wenn es einmalig auf einem Laptop läuft. Machen Sie die Erstellung zu einem Build-Schritt. Aus jedem Build sollte eine SBOM hervorgehen, wie ein Testbericht.
Ein minimaler GitHub-Actions-Job, der die SBOM erstellt und als Artefakt aufbewahrt:
Zwei Dinge verdienen ihren Platz. Java 21 mit setup-java festzupinnen verhindert das stille Hängen unter älteren JDKs. bom.json als Artefakt hochzuladen bewahrt die Datei nach dem Lauf auf. Genau darum geht es, wenn man sie in der CI erzeugt.
Sie pushen an einen Dependency-Track-Server? cdxgen übermittelt direkt. Legen Sie URL und API-Key als Repository-Secrets an.
Azure Pipelines
Derselbe Job in Azure Pipelines. Gleiche Form: Java 21 einrichten, cdxgen installieren, erzeugen, die Datei veröffentlichen, damit sie den Agent überlebt.
Für einen containerisierten Build tauschen Sie die Install-und-Run-Zeilen gegen das Docker-Image und binden den Workspace ein. Das erspart das Node- und Java-Setup.
Fallstricke bei cdxgen-SBOMs
cdxgen erzeugt für nahezu alles eine Datei. Ob diese Datei vollständig ist, hängt vom Ökosystem ab – und davon, ob das Projekt beim Scannen gebaut ist. Das trifft Teams, die annehmen, jede SBOM habe dieselbe Tiefe.
Der größte Hebel ist der Build-Lebenszyklus. Standardmäßig erzeugt cdxgen bei Anwendungen in der Build-Phase. Die Tiefe hängt bei mehreren Ökosystemen davon ab, dass das Projekt zuvor wiederhergestellt (restored) oder gebaut wurde. Scans vor dem Build sind in der CI schneller und sicherer. Sie können aber den vollständigen transitiven Baum verfehlen. Wissen Sie, in welchem Modus Sie sind.
Ökosystem | Transitive Tiefe | Was es braucht | Worauf zu achten ist |
|---|---|---|---|
Java (Maven) | Vollständig | Auflösbare POM; Maven ist Standard vor Gradle | Gradle mit |
JavaScript / Node | Vollständig | Vorhandene Lockfile | Ohne Lockfile nur direkte Abhängigkeiten, eine flache BOM |
Python | Gut | Java 21 installiert |
|
Go | Gut | Modulbewusstes Projekt | Nur-Binär erfordert |
.NET | Vollständig erst nach Restore |
| Container-Image bündelt SDK 8.0; ein Versionskonflikt lässt den Baum entfallen |
C / C++ | Teilweise | Echter Build-Kontext, Java 21 | Ein bloßer Quellbaum ergibt eine dünne BOM; zuerst bauen |
Rust, Ruby, PHP | Gut | Standard-Manifeste und -Lockfiles | Abdeckung solide; anhand Ihres Projekts überprüfen |
Gewohnheiten, die die BOM vollständig halten:
Geben Sie immer
-tan. Die automatische Erkennung funktioniert meist. Wenn sie falsch rät, ist die BOM still unvollständig. Den Typ zu benennen beseitigt das Raten.Bauen oder restoren Sie vor dem Scannen bei .NET, C/C++ und allem, was den vollständigen Baum benötigt. Ein Scan vor dem Build ist nicht falsch. Er ist flacher. Wissen Sie, welchen Sie ausgeliefert haben.
Prüfen Sie auf eine Lockfile. Bei Node und Ähnlichem bedeutet keine Lockfile nur direkte Abhängigkeiten. Eine BOM mit nur direkten Abhängigkeiten besteht ein Audit und verbirgt dabei den Großteil Ihrer Lieferkette.
Validieren Sie die Ausgabe. cdxgen validiert standardmäßig gegen das Schema. Lassen Sie das eingeschaltet. Behandeln Sie eine Warnung als Signal zum Hinsehen, nicht als überspringbare Zeile.
Pinnen Sie die Spezifikationsversion. Machen Sie
--spec-versionzu einer bewussten Wahl. Die Version, die Sie ausgeben, ist die Version, gegen die ein Kunde oder eine Behörde prüft.
Keiner dieser Punkte ist ein Grund, cdxgen zu meiden. Sie sind der Unterschied zwischen einer BOM, die fertig aussieht, und einer, die es ist.
C/C++ und Embedded: der schwierigste Fall
In der Fallstricke-Tabelle steht C/C++ auf „teilweise", weil ein generischer Generator – cdxgen eingeschlossen – in diesen Ökosystemen am wenigsten Anhaltspunkte hat. Und die Lücke zwischen dem, was ein Tool meldet, und dem, was tatsächlich ausgeliefert wird, ist hier die größte der Branche.
Die konkreten Fallen:
Kein Abhängigkeitsmanifest als Ausgangspunkt. Node hat eine Lockfile, Python hat eine, Rust und Go haben eine. C/C++ hat nichts Vergleichbares. Conan, vcpkg und CMake FetchContent helfen, wenn sie eingesetzt werden, doch die meisten Embedded-Projekte bauen mit schlichten Makefiles, IAR oder STM32CubeIDE – es gibt also keinen maschinenlesbaren Graphen zum Parsen.
Einkopierter Quellcode verschwindet in Ihrem Baum. Bibliotheken wie lwIP, mbedTLS oder nlohmann/json werden direkt ins Projekt kopiert, und sind sie einmal kopiert, sehen sie aus wie Eigencode. Ein Generator, der nur Manifeste liest, sieht sie nie. Sie zu erkennen erfordert Fingerprinting gegen einen Korpus bekannter Releases, und sobald der Code gepatcht ist, scheitert der exakte Abgleich und Sie landen beim unscharfen Abgleich mit echter Unsicherheit.
Statische .a-Archive sind nahezu Blackboxes. Eine vor Monaten aus einkopiertem Quellcode gebaute libfoo.a trägt einen Dateinamen und wenig sonst. Kein Lieferant, keine Upstream-Version, keines der NTIA-Mindestelemente. Die Linker-Inspektion mit -l liefert Ihnen bestenfalls einen Namen, und Embedded-Builds kompilieren RTOS, HAL und Krypto oft aus dem Quellcode ganz ohne -l-Flags.
Das Inventarisieren des Vendor-Ordners zählt zu viel. Ein gemeinsames vendor/-Verzeichnis enthält viele Bibliotheken, aber ein einzelnes Build-Ziel nutzt nur einige davon. Den ganzen Ordner zu listen bringt Komponenten in die SBOM, die nicht im Binary sind, was sich in jedem nachgelagerten Schwachstellenscan in Fehlalarme verwandelt. --gc-sections verschärft das: Code, der kompiliert, aber nie aufgerufen wird, trägt null Bytes zum Image bei, doch ein naiver Scan meldet ihn trotzdem.
Silizium-Hersteller-SDKs erzeugen Rauschen. ST, NXP, TI und Renesas liefern geforkte, umbenannte, angepasste Kopien von FreeRTOS, lwIP und mbedTLS innerhalb ihrer SDKs. Diese gegen Upstream-Releases zu fingerprinten ist ohne herstellerspezifische Erkennung unzuverlässig.
Eine korrekte Embedded-C/C++-SBOM muss aus dem stammen, was der Build für ein bestimmtes Ziel tatsächlich kompiliert und linkt, korreliert mit der Erkennung von einkopiertem Code und Plattformbewusstsein. Diese Details können nur aus einer Analyse zur Build-Zeit kommen, nicht aus dem Parsen von Manifesten – und das liegt außerhalb dessen, wofür cdxgen gebaut ist.
Genau um dieses Problem herum ist lynkctl konzipiert, Interlynks SBOM-Generator für Embedded C/C++: toolchain-bewusste Extraktion aus GNU Make, CMake und IAR, gepaart mit einem kuratierten Index von Embedded-Open-Source-Komponenten für die einkopierte Schicht. Wenn Ihr Ziel Firmware ist, beginnen Sie dort, statt einen Allzweck-Generator zu einem Fall zu zwingen, für den er nie gedacht war. Unsere vollständige Aufschlüsselung, warum das schwierig ist, finden Sie in „The State of SBOM Generation for C/C++".
Über die SBOM-Erstellung hinaus
Eine Sache entscheidet noch, ob Ihr SBOM-Programm standhält.
cdxgen ist ein Generator. Es betrachtet ein Projekt, ein Image oder einen Build und erzeugt eine korrekte CycloneDX-Datei. Das macht es gut. Jeder Befehl oben ist echt. Für eine einzelne Codebasis haben Sie jetzt, was Sie brauchen.
Ein Generator verwaltet nicht, was er erzeugt. Das ist kein Vorwurf an cdxgen. Es ist die Kategorie. Wechseln Sie von einem Projekt zu einem Portfolio, und ein anderer Satz Probleme taucht auf. Keines davon ist ein Erstellungsproblem.
Sie erzeugen nicht eine SBOM. Sie erzeugen Tausende – eine pro Build pro Service pro Release. Sie stapeln sich schneller, als irgendjemand sie liest.
Verschiedene Teams geben verschiedene Formate und Versionen aus. Dieselbe Komponente wird auf drei Arten benannt. Nichts lässt sich sauber über Produkte hinweg aggregieren.
Jede SBOM ist eine Momentaufnahme. Korrekt zur Build-Zeit, blind für das CVE, das nächste Woche offengelegt wird. Eine Datei auf der Platte prüft sich nicht selbst neu.
Auch Lieferanten senden SBOMs, in welcher Form sie wollen. Die müssen validiert und mit Ihren eigenen zusammengeführt werden.
Die Datei zu erzeugen besteht das Audit. Die Frage „Wo sind wir exponiert – über alles hinweg, was wir ausliefern, und zwar jetzt?" zu beantworten, ist ein anderes System. Welches Sie gebaut haben, erfahren Sie, wenn zum ersten Mal an einem Freitag ein kritisches CVE einschlägt.
Nutzen Sie also cdxgen. Es ist das richtige Tool für den Schritt, den es abdeckt. Dimensionieren Sie den Schritt nur korrekt. Die Erstellung ist der Anfang eines SBOM-Programms, nicht das Ganze.
Zusammenfassung
Installieren Sie cdxgen. Führen Sie cdxgen -t <type> --spec-version 1.6 -o bom.json aus. Ergänzen Sie --evidence für den Beweis und --with-reachables, um Schwachstellen-Rauschen zu reduzieren. Signieren Sie, was das Haus verlässt. Verdrahten Sie es in GitHub Actions oder Azure Pipelines, damit es bei jedem Build läuft.
Achten Sie auf die Tiefen-Fallstricke. Geben Sie -t explizit an. Bauen oder restoren Sie vor dem Scannen der Ökosysteme, die es benötigen. Bestätigen Sie, dass eine Lockfile vorhanden ist, sonst liefern Sie eine BOM mit nur direkten Abhängigkeiten aus.
Das liefert Ihnen korrekte, aktuelle CycloneDX-Dateien. Einen Stapel Dateien in eine Antwort zu verwandeln, der Sie unter Druck vertrauen können, erfordert die Schicht, die darüber sitzt. Planen Sie dafür, bevor Sie sie brauchen, nicht danach.
Interlynk gibt Sicherheits- und Compliance-Teams ein einziges System of Record für jede SBOM – aus cdxgen oder jedem anderen Generator, intern oder von Lieferanten – mit normalisierter Komponentenidentität und eingebauter kontinuierlicher Überwachung. Halten Sie jede Ausgabe aktuell, während sich Ihre Abhängigkeiten und die Offenlegungen weiterentwickeln, und beantworten Sie die portfolioweite Expositionsfrage in Minuten statt Tagen. Vertraut von Sicherheits- und Compliance-Teams in über 100 regulierten Unternehmen.