Diagram van cdxgen die uit software een CycloneDX-SBOM genereert: links een kleine doos met verstrengelde componenten, in het midden een prominente terminal die cdxgen uitvoert, en rechts een uitgesplitste SBOM met groene, oranje en rode risicolabels, Interlynk

Een praktische gids voor het genereren van CycloneDX-SBOM's met cdxgen voor Node, Python, Java, Go, C/C++ en containers – en wat er verder gaat dan het genereren van de eerste SBOM.

Opmerking: Deze gids is medio juli 2026 gecontroleerd tegen de op dat moment actuele cdxgen-releases. cdxgen wordt actief doorontwikkeld; latere releases kunnen functies toevoegen, bugs verhelpen of het gedrag wijzigen. Raadpleeg de officiële cdxgen-documentatie voor de huidige flags en commando's voordat u op een van de onderstaande voorbeelden vertrouwt.

OWASP cdxgen is de snelste manier om een codebase om te zetten in een CycloneDX-SBOM. Het is de officiële generator in het CycloneDX-ecosysteem.

cdxgen dekt de meeste moderne talen en produceert met één commando een geldige SBOM. Als uw doel vandaag „geef mij een SBOM" is, is dit de tool waarop u kunt vertrouwen.

Deze gids helpt u uw eerste SBOM te krijgen, optionele details erin op te nemen en het genereren van SBOM's in pipelines te operationaliseren. Vervolgens trekt hij een grens die de meeste SBOM-content overslaat. Het bestand genereren is één stap. Het daarna gebruiken is een andere. Weten waar de een eindigt en de ander begint, bespaart u later een verkeerde aanname.

cdxgen installeren

Drie manieren om cdxgen te installeren:

# npm (Node 20+)
npm install -g @cyclonedx/cdxgen


# Homebrew
brew install cdxgen


# Docker
docker pull ghcr.io/cyclonedx/cdxgen
# npm (Node 20+)
npm install -g @cyclonedx/cdxgen


# Homebrew
brew install cdxgen


# Docker
docker pull ghcr.io/cyclonedx/cdxgen
# npm (Node 20+)
npm install -g @cyclonedx/cdxgen


# Homebrew
brew install cdxgen


# Docker
docker pull ghcr.io/cyclonedx/cdxgen

Eén vereiste laat mensen struikelen. C, C++ en Python hebben Java 21 of nieuwer op de machine nodig. cdxgen loopt vast op Java 8 of 11. Installeer een actuele JDK en stel eerst JAVA_HOME in, anders blijft de run zonder duidelijke reden hangen.

Eerste SBOM genereren

Ga naar de projectmap en voer één commando uit.

cdxgen -o bom.json
cdxgen -o bom.json
cdxgen -o bom.json

Dat produceert een CycloneDX-bestand, bom.json. cdxgen detecteert automatisch het projecttype en heeft het meestal bij het rechte eind. Als het ernaast zit, is de uitvoer dun of onjuist. Benoem het type vanaf dag één expliciet met -t.

cdxgen -t java -o bom.json
cdxgen -t python -o bom.json
cdxgen -t javascript -o bom.json
cdxgen -t go -o bom.json
cdxgen -t java -o bom.json
cdxgen -t python -o bom.json
cdxgen -t javascript -o bom.json
cdxgen -t go -o bom.json
cdxgen -t java -o bom.json
cdxgen -t python -o bom.json
cdxgen -t javascript -o bom.json
cdxgen -t go -o bom.json

Voor een repository met meerdere services scant u recursief. cdxgen stelt er één geaggregeerde BOM van samen.

cdxgen -r -o bom.json
cdxgen -r -o bom.json
cdxgen -r -o bom.json

Stel de specificatieversie bewust in. De versie die u uitgeeft, is de versie waaraan klanten en toezichthouders u houden.

cdxgen -t java --spec-version 1.6 -o bom.json
cdxgen -t java --spec-version 1.6 -o bom.json
cdxgen -t java --spec-version 1.6 -o bom.json


Dekking van ecosystemen

cdxgen wint op breedte. Eén tool vervangt een lade vol taalspecifieke plug-ins. De gangbare aanroepen:

Python: cdxgen -t python. Leest requirements-bestanden, Poetry en PDM. Vereist Java 21.

Java / Maven / Gradle: cdxgen -t java. Lost de volledige boom op, niet alleen de directe declaraties.

Node / npm: cdxgen -t javascript. Doorloopt de lockfile voor de echte transitieve grafiek.

Go: cdxgen -t go.

C / C++: cdxgen -t c. Java 21 vereist. Beste resultaten uit een echte build, niet uit een kale bronboom.

Containers: cdxgen -t docker alpine:3.20 -o bom.json. Haalt OS-pakketten en taalafhankelijkheden uit de image.

Wilt u dit in de CI opnemen? Controleer uw ecosysteem eerst tegen de lijst met ondersteunde projecttypen (Supported Project Types). De dekking is breed, niet universeel. Beter een hiaat vinden voordat een pipeline ervan afhankelijk is.

Bewijs van componentgebruik opnemen

Een basale SBOM somt op wat uw manifesten declareren. Dat is een bewering. Bewijs (evidence) is het bewijs. Voor een gereguleerde indiening telt dat verschil.

cdxgen --evidence -t java -o bom.json
cdxgen --evidence -t java -o bom.json
cdxgen --evidence -t java -o bom.json

De flag --evidence (cdxgen 9.9 en later) legt vast waar elke component wordt gebruikt, niet alleen wat een manifest declareerde. Ga verder met call-stack-bewijs. Het toont of een kwetsbare functie bereikbaar is vanuit uw code.

cdxgen --with-reachables -t java -o bom.json
cdxgen --with-reachables -t java -o bom.json
cdxgen --with-reachables -t java -o bom.json

Bereikbaarheid (reachability) verdient zichzelf terug. De meeste scanners markeren elke kwetsbare afhankelijkheid. Veel ervan zitten in codepaden die u nooit aanroept. Call-stack-bewijs laat zien welke bevindingen uw code daadwerkelijk raken. Dat is het verschil tussen een triagewachtrij van vierhonderd en een van twaalf.

SBOM ondertekenen

Een niet-ondertekende SBOM is een tekstbestand dat iedereen kan bewerken. Gaat hij naar een klant of toezichthouder? Onderteken hem.

cdxgen --generate-key-and-sign -t java -o bom.json
cdxgen --generate-key-and-sign -t java -o bom.json
cdxgen --generate-key-and-sign -t java -o bom.json

Dat genereert een sleutelpaar en voegt een handtekening toe. Stroomafwaarts bevestigt cdx-verify dat het bestand sinds de ondertekening onveranderd is. Gebruik in productie uw eigen beheerde sleutels, niet een gegenereerd testpaar. Het mechanisme is ingebouwd. Zet het vroeg aan.

Opnemen in CI: GitHub Actions, Azure DevOps

GitHub Actions

Niets hiervan helpt als het eenmalig op een laptop draait. Maak het genereren een buildstap. Uit elke build hoort een SBOM te komen, net als een testrapport.

Een minimale GitHub Actions-job die de SBOM genereert en als artefact bewaart:

name: Generate SBOM
on: [push]

jobs:
  sbom:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: '21'   # vereist voor C/C++ en Python

      - name: Generate CycloneDX SBOM
        run: |
          npm install -g @cyclonedx/cdxgen
          cdxgen -r -t java --spec-version 1.6 --evidence -o bom.json

      - name: Upload SBOM
        uses: actions/upload-artifact@v4
        with:
          name: sbom
          path

name: Generate SBOM
on: [push]

jobs:
  sbom:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: '21'   # vereist voor C/C++ en Python

      - name: Generate CycloneDX SBOM
        run: |
          npm install -g @cyclonedx/cdxgen
          cdxgen -r -t java --spec-version 1.6 --evidence -o bom.json

      - name: Upload SBOM
        uses: actions/upload-artifact@v4
        with:
          name: sbom
          path

name: Generate SBOM
on: [push]

jobs:
  sbom:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: '21'   # vereist voor C/C++ en Python

      - name: Generate CycloneDX SBOM
        run: |
          npm install -g @cyclonedx/cdxgen
          cdxgen -r -t java --spec-version 1.6 --evidence -o bom.json

      - name: Upload SBOM
        uses: actions/upload-artifact@v4
        with:
          name: sbom
          path

Twee dingen verdienen hun plaats. Java 21 vastzetten met setup-java voorkomt het stille vastlopen op oudere JDK's. bom.json als artefact uploaden bewaart het bestand na de run. Dat is het hele punt van genereren in de CI.

Pusht u naar een Dependency-Track-server? cdxgen dient direct in. Zet de URL en API-key als repository-secrets.

      - name: Generate and submit
        env:
          FETCH_LICENSE: "true"
          SERVER_URL: ${{ secrets.DTRACK_URL }}
          API_KEY: ${{ secrets.DTRACK_API_KEY }}
        run: |
          npm install -g @cyclonedx/cdxgen
          cdxgen -r -t java --spec-version 1.6 -o bom.json \
            --server-url "$SERVER_URL" --api-key "$API_KEY"
      - name: Generate and submit
        env:
          FETCH_LICENSE: "true"
          SERVER_URL: ${{ secrets.DTRACK_URL }}
          API_KEY: ${{ secrets.DTRACK_API_KEY }}
        run: |
          npm install -g @cyclonedx/cdxgen
          cdxgen -r -t java --spec-version 1.6 -o bom.json \
            --server-url "$SERVER_URL" --api-key "$API_KEY"
      - name: Generate and submit
        env:
          FETCH_LICENSE: "true"
          SERVER_URL: ${{ secrets.DTRACK_URL }}
          API_KEY: ${{ secrets.DTRACK_API_KEY }}
        run: |
          npm install -g @cyclonedx/cdxgen
          cdxgen -r -t java --spec-version 1.6 -o bom.json \
            --server-url "$SERVER_URL" --api-key "$API_KEY"

Azure Pipelines

Dezelfde job in Azure Pipelines. Zelfde vorm: Java 21 opzetten, cdxgen installeren, genereren, het bestand publiceren zodat het de agent overleeft.

trigger:
  - main

pool:
  vmImage: ubuntu-latest

steps:
  - task: JavaToolInstaller@0
    inputs:
      versionSpec: '21'
      jdkArchitectureOption: 'x64'
      jdkSourceOption: 'PreInstalled'

  - script: |
      npm install -g @cyclonedx/cdxgen
      cdxgen -r -t java --spec-version 1.6 --evidence -o $(Build.ArtifactStagingDirectory)/bom.json
    displayName: 'Generate CycloneDX SBOM'

  - task: PublishBuildArtifacts@1
    inputs:
      PathtoPublish: '$(Build.ArtifactStagingDirectory)/bom.json'
      ArtifactName: 'sbom'
    displayName: 'Publish SBOM'
trigger:
  - main

pool:
  vmImage: ubuntu-latest

steps:
  - task: JavaToolInstaller@0
    inputs:
      versionSpec: '21'
      jdkArchitectureOption: 'x64'
      jdkSourceOption: 'PreInstalled'

  - script: |
      npm install -g @cyclonedx/cdxgen
      cdxgen -r -t java --spec-version 1.6 --evidence -o $(Build.ArtifactStagingDirectory)/bom.json
    displayName: 'Generate CycloneDX SBOM'

  - task: PublishBuildArtifacts@1
    inputs:
      PathtoPublish: '$(Build.ArtifactStagingDirectory)/bom.json'
      ArtifactName: 'sbom'
    displayName: 'Publish SBOM'
trigger:
  - main

pool:
  vmImage: ubuntu-latest

steps:
  - task: JavaToolInstaller@0
    inputs:
      versionSpec: '21'
      jdkArchitectureOption: 'x64'
      jdkSourceOption: 'PreInstalled'

  - script: |
      npm install -g @cyclonedx/cdxgen
      cdxgen -r -t java --spec-version 1.6 --evidence -o $(Build.ArtifactStagingDirectory)/bom.json
    displayName: 'Generate CycloneDX SBOM'

  - task: PublishBuildArtifacts@1
    inputs:
      PathtoPublish: '$(Build.ArtifactStagingDirectory)/bom.json'
      ArtifactName: 'sbom'
    displayName: 'Publish SBOM'

Voor een gecontaineriseerde build vervangt u de install-en-run-regels door de Docker-image en koppelt u de workspace aan. Dat slaat de Node- en Java-setup over.

  - script: |
      docker run --rm -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen \
        -r /app -t java --spec-version 1.6 -o /app/bom.json
    displayName: 'Generate SBOM (container)'
  - script: |
      docker run --rm -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen \
        -r /app -t java --spec-version 1.6 -o /app/bom.json
    displayName: 'Generate SBOM (container)'
  - script: |
      docker run --rm -v $(pwd):/app:rw -t ghcr.io/cyclonedx/cdxgen \
        -r /app -t java --spec-version 1.6 -o /app/bom.json
    displayName: 'Generate SBOM (container)'


Valkuilen bij cdxgen-SBOM's

cdxgen produceert voor bijna alles een bestand. Of dat bestand volledig is, hangt af van het ecosysteem – en van de vraag of het project is gebouwd op het moment dat u scant. Dit treft teams die aannemen dat elke SBOM dezelfde diepte heeft.

De grootste hefboom is de build-levenscyclus. Standaard genereert cdxgen voor applicaties in de buildfase. De diepte hangt bij meerdere ecosystemen af van of het project eerst is hersteld (restored) of gebouwd. Scans vóór de build zijn in de CI sneller en veiliger. Ze kunnen echter de volledige transitieve boom missen. Weet in welke modus u zit.

Ecosysteem

Transitieve diepte

Wat het nodig heeft

Waarop te letten

Java (Maven)

Volledig

Oplosbare POM; Maven is standaard vóór Gradle

Forceer Gradle met -t gradle; SBT met -t scala

JavaScript / Node

Volledig

Aanwezige lockfile

Geen lockfile betekent alleen directe afhankelijkheden, een ondiepe BOM

Python

Goed

Java 21 geïnstalleerd

--no-install-deps geeft een BOM vóór de build waarin transitieve kunnen ontbreken

Go

Goed

Module-bewust project

Alleen-binair vereist --lifecycle post-build

.NET

Volledig pas na restore

dotnet restore en een passende SDK

Container-image bundelt SDK 8.0; een versieconflict laat de boom vervallen

C / C++

Gedeeltelijk

Een echte buildcontext, Java 21

Een kale bronboom levert een dunne BOM; bouw eerst

Rust, Ruby, PHP

Goed

Standaardmanifesten en lockfiles

Dekking solide; verifieer tegen uw project

Gewoonten die de BOM volledig houden:

  • Geef altijd -t op. Automatische detectie werkt meestal. Als ze verkeerd raadt, is de BOM stilletjes onvolledig. Het type benoemen haalt het raden weg.

  • Bouw of restore vóór het scannen bij .NET, C/C++ en alles wat de volledige boom nodig heeft. Een scan vóór de build is niet fout. Hij is ondieper. Weet welke u hebt uitgeleverd.

  • Controleer op een lockfile. Bij Node en dergelijke betekent geen lockfile alleen directe afhankelijkheden. Een BOM met alleen directe afhankelijkheden doorstaat een audit en verbergt daarbij het grootste deel van uw toeleveringsketen.

  • Valideer de uitvoer. cdxgen valideert standaard tegen het schema. Houd dat aan. Behandel een waarschuwing als een signaal om te kijken, niet als een over te slaan regel.

  • Zet de specificatieversie vast. Maak van --spec-version een bewuste keuze. De versie die u uitgeeft, is de versie waartegen een klant of toezichthouder controleert.

Geen van deze punten is een reden om cdxgen te mijden. Ze zijn het verschil tussen een BOM die af lijkt en een die het is.

C/C++ en embedded: het lastigste geval

In de valkuilentabel staat C/C++ op „gedeeltelijk", omdat een generieke generator – cdxgen inbegrepen – in die ecosystemen het minste heeft om mee te werken. En de kloof tussen wat een tool rapporteert en wat daadwerkelijk wordt uitgeleverd, is hier de grootste van de branche.

De specifieke valkuilen:

Geen afhankelijkheidsmanifest als vertrekpunt. Node heeft een lockfile, Python heeft er een, Rust en Go hebben er een. C/C++ heeft niets vergelijkbaars. Conan, vcpkg en CMake FetchContent helpen wanneer ze worden gebruikt, maar de meeste embedded projecten bouwen met kale Makefiles, IAR of STM32CubeIDE, dus er is geen machineleesbare grafiek om te parsen.

Ingekopieerde broncode verdwijnt in uw boom. Bibliotheken als lwIP, mbedTLS of nlohmann/json worden rechtstreeks in het project gekopieerd, en eenmaal gekopieerd zien ze eruit als eigen code. Een generator die alleen manifesten leest, ziet ze nooit. Ze detecteren vereist fingerprinting tegen een corpus van bekende releases, en zodra de code is gepatcht, faalt exacte matching en zit u in fuzzy matching met echte onzekerheid.

Statische .a-archieven zijn bijna blackboxes. Een libfoo.a die maanden geleden uit ingekopieerde broncode is gebouwd, draagt een bestandsnaam en weinig anders. Geen leverancier, geen upstream-versie, geen van de NTIA-minimumelementen. Linker-inspectie met -l geeft u hooguit een naam, en embedded builds compileren RTOS, HAL en crypto vaak uit broncode zonder enige -l-flag.

Het inventariseren van de vendor-map telt te veel. Een gedeelde vendor/-map bevat veel bibliotheken, maar een enkel buildtarget gebruikt er slechts enkele. De hele map opsommen zet componenten in de SBOM die niet in de binary zitten, wat in elke stroomafwaartse kwetsbaarheidsscan tot valse positieven leidt. --gc-sections maakt dit erger: code die compileert maar nooit wordt aangeroepen, draagt nul bytes bij aan de image, maar een naïeve scan rapporteert hem toch.

Silicon-leverancier-SDK's voegen ruis toe. ST, NXP, TI en Renesas leveren geforkte, hernoemde, aangepaste kopieën van FreeRTOS, lwIP en mbedTLS binnen hun SDK's. Deze tegen upstream-releases fingerprinten is onbetrouwbaar zonder leveranciersspecifieke detectie.

Een accurate embedded C/C++-SBOM moet voortkomen uit wat de build daadwerkelijk compileert en linkt voor een specifiek doel, gecorreleerd met detectie van ingekopieerde code en platformbewustzijn. Die details kunnen alleen komen uit analyse tijdens de build, niet uit het parsen van manifesten – en dat valt buiten waarvoor cdxgen is gebouwd.

Dit is het probleem waar lynkctl, Interlynks SBOM-generator voor embedded C/C++, omheen is ontworpen: toolchain-bewuste extractie uit GNU Make, CMake en IAR, gekoppeld aan een gecureerde index van embedded open-sourcecomponenten voor de ingekopieerde laag. Als uw doel firmware is, begin daar in plaats van een generieke generator te dwingen een geval te dekken waarvoor hij nooit was bedoeld. Onze volledige uiteenzetting waarom dit moeilijk is, staat in „The State of SBOM Generation for C/C++".

Verder dan het genereren van SBOM's

Eén ding bepaalt nog of uw SBOM-programma standhoudt.

cdxgen is een generator. Het bekijkt één project, één image of één build en produceert een accuraat CycloneDX-bestand. Dat doet het goed. Elk commando hierboven is echt. Voor één codebase hebt u nu wat u nodig hebt.

Een generator beheert niet wat hij genereert. Dat is geen kritiek op cdxgen. Het is de categorie. Ga van één project naar een portfolio en er duikt een andere reeks problemen op. Geen daarvan is een generatieprobleem.

U produceert niet één SBOM. U produceert er duizenden – één per build per service per release. Ze stapelen zich sneller op dan iemand ze leest.

Verschillende teams geven verschillende formaten en versies uit. Dezelfde component krijgt op drie manieren een naam. Niets aggregeert netjes over producten heen.

Elke SBOM is een momentopname. Accuraat op buildtijd, blind voor de CVE die volgende week wordt geopenbaard. Een bestand op schijf controleert zichzelf niet opnieuw.

Ook leveranciers sturen SBOM's, in welke vorm ze maar willen. Die moeten worden gevalideerd en samengevoegd met uw eigen.

Het bestand genereren doorstaat de audit. De vraag „Waar zijn we blootgesteld, over alles heen wat we uitleveren, en wel nú?" beantwoorden is een ander systeem. Welke u hebt gebouwd, ontdekt u wanneer voor het eerst op een vrijdag een kritieke CVE inslaat.

Gebruik dus cdxgen. Het is de juiste tool voor de stap die het bezit. Dimensioneer die stap alleen correct. Genereren is het begin van een SBOM-programma, niet het geheel ervan.

Samenvatting

Installeer cdxgen. Voer cdxgen -t <type> --spec-version 1.6 -o bom.json uit. Voeg --evidence toe voor bewijs, en --with-reachables om kwetsbaarheidsruis te verminderen. Onderteken wat het pand verlaat. Verwerk het in GitHub Actions of Azure Pipelines zodat het bij elke build draait.

Let op de dieptevalkuilen. Geef -t expliciet op. Bouw of restore vóór het scannen van de ecosystemen die dat nodig hebben. Bevestig dat er een lockfile aanwezig is, anders levert u een BOM met alleen directe afhankelijkheden uit.

Dat geeft u accurate, actuele CycloneDX-bestanden. Een stapel bestanden omzetten in een antwoord dat u onder druk kunt vertrouwen, vergt de laag die erbovenop zit. Plan daarvoor voordat u het nodig hebt, niet erna.

Interlynk geeft security- en complianceteams één system of record voor elke SBOM – uit cdxgen of welke andere generator dan ook, intern of van leveranciers – met genormaliseerde componentidentiteit en ingebouwde continue monitoring. Houd elke uitvoer actueel terwijl uw afhankelijkheden en de openbaarmakingen evolueren, en beantwoord de portfoliobrede blootstellingsvraag in minuten in plaats van dagen. Vertrouwd door security- en complianceteams bij meer dan 100 gereguleerde bedrijven.

Demo boeken · Gratis starten

Vertrouwd door beveiligings- en complianceteams bij meer dan 100 gereguleerde bedrijven.

Zie uw SBOM zoals het hoort

Interlynk automatiseert SBOM's, beheert open source-risico's, monitort leveranciers en bereidt u voor op het post-quantumtijdperk – alles in één vertrouwd platform.

Vertrouwd door beveiligings- en complianceteams bij meer dan 100 gereguleerde bedrijven.

Interlynk automatiseert SBOM's, beheert open-sourcerisico's, monitort leveranciers en bereidt u voor op het post-quantumtijdperk, allemaal op één vertrouwd platform.

Audit-klare SBOM. Bij elke build.

Vertrouwd door beveiligings- en complianceteams bij meer dan 100 gereguleerde bedrijven.

Interlynk automatiseert SBOM's, beheert open-sourcerisico's, monitort leveranciers en bereidt u voor op het post-quantumtijdperk, allemaal op één vertrouwd platform.

Audit-klare SBOM. Bij elke build.