Self-hosted service
cdxgen/cdxgen avatar
cdxgen/cdxgen

cdxgen: one command that emits seven kinds of BOM, from source or container image

Creates CycloneDX Bill of Materials (BOM) for your projects from source and container images. Supports many languages and package managers. Integrate in your CI/CD pipeline with automatic submission to Dependency Track server

1,092 stars267 forksJavaScriptApache-2.0

At a glance

What is it?
cdxgen is a CLI, library, REPL and server that generates CycloneDX bills of materials for source trees and container images, with separate commands for hardware, operations, AI and attestation documents. This looks at what the tool covers, how its profiles shape the output, and where a BOM generator stops short of a scanner.
Who is it for?
cdxgen fits a build or release team that has to emit a machine-readable inventory of what is inside a project or image, that needs the CycloneDX format rather than a bespoke report, and that wants the same generator available as a library, a REPL and a long running server.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Seven kinds of bill of materials, one generator

cdxgen is a CLI tool, library, REPL and server for creating, validating, signing and verifying software bills of materials. The breadth is the point. Where a typical dependency lister produces one document listing libraries, cdxgen produces a family of documents, each aimed at a different question.

The formats listed in the project documentation are: hardware BOM for supported live hosts such as Apple Silicon macOS and Linux amd64 and arm64 systems; software BOM for many languages and container images; cryptography BOM for Java keystores and certificates, plus JavaScript and TypeScript source level algorithm inventory; operations BOM for Linux container images and VMs running Linux or Windows; SaaSBOM for Java, Python, JavaScript, TypeScript and PHP projects; AI/ML BOM for prompt files, AI services, MCP configs and model metadata with explainable AI governance, security, performance and agentic findings; and attestations, which generate an SBOM with templates for multiple standards and let you sign the document at a granular level to improve authenticity.

The audience is a supply chain security team that has to produce this as a repeatable artefact in CI, and the tool is explicit that the output can be pushed downstream automatically, for example by submitting to a Dependency Track server.

The practical advantage over doing this by hand is not the format. It is that a single tool can produce the same inventory for a source tree and for the image built from it, which is where the two normally disagree.

CycloneDX 1.6, 1.7 and 2.0, with a downgrade path

The output format story is the part to look at first, because a BOM generator is only useful if the consumer can read what it writes.

The project documentation states that cdxgen generates CycloneDX JSON BOMs and supports SPDX 3.0.1 JSON-LD export, and that the tool targets CycloneDX specification versions 1.6, 1.7 and 2.0, with the output able to be downgraded to 1.4 or 1.5 for legacy consumers. The native document format is CycloneDX JSON, and the SPDX route is reached with `cdxgen --format spdx` or through a separate converter.

That downgrade path is the detail that makes the tool practical in an organisation where the security tooling upgrades slower than the build system. A consumer stuck on 1.5 does not have to block the pipeline, and the same generator can be rolled out before the readers are updated.

The output document formats are listed as exactly two, CycloneDX JSON as the primary native format and SPDX 3.0.1 JSON-LD. There is no XML or YAML output listed, which matters if your ingestion tooling expects one.

Separate commands for separate jobs, not one flag for everything

The project documentation organises itself around personas, and each persona has its own entry point command. The developer path generates a CycloneDX BOM from a local repo, git URL, purl or container image:

bash
cdxgen -o bom.json .

The AI platform team command is `aibom .`, the hardware team command is `hbom -o hbom.json`, and the SOC analyst command builds an operations BOM for a live host:

bash
obom -o obom.json --deep --bom-audit --bom-audit-categories obom-runtime

Compliance teams get a validator and a converter, `cdx-validate -i bom.json --benchmark scvs-l2,cra` and `cdx-convert`. Security teams get `tracebom --cmd "npm test" --trace-crypto -o cbom.json`, which traces an execution dynamically to capture cryptographic activity and services rather than reading the manifest.

The split into distinct binaries is a design choice with a practical consequence. A pipeline that wants an SBOM and a pipeline that wants a hardware inventory do not need to agree on flags, and each command keeps its own options legible. It also means the tool is not one program with a hundred switches, which is a maintenance advantage, and a small discoverability cost for anyone who does not know which binary they need.

Running it as a server in a container

cdxgen can run as a server, and the repository ships a compose file that shows the intended shape. The service builds from `./ci/Dockerfile` with the repository as context, publishes port 9090, and starts the server bound to all interfaces:

yaml
    environment:
      - NODE_COMPILE_CACHE=/tmp/cdxgen-node-cache # Using compile cache improves cold start performance
      - FETCH_LICENSE=false # Set this to true to always include license
      - CDXGEN_DEBUG_MODE=info # Set this to debug to get more console output
    ports:
      - "9090:9090"
    command: cdxgen --server --server-host 0.0.0.0 --server-port 9090

Two of those environment variables deserve attention. `FETCH_LICENSE` defaults to false here, and the comment says to set it to true to always include license, which tells you the licence field is populated conditionally rather than always. `CDXGEN_DEBUG_MODE=info` raises the console output, and the comment says to set it to debug for more.

The volume mapping in the compose file mounts your home directory to `/app`, with a comment that it is the directory containing sources, which is how the server reaches a project to scan. The compose file also carries OpenContainers annotations naming CycloneDX as the image vendor and Apache-2.0 as the licence, and a commented line for the published image at `ghcr.io/cdxgen/cdxgen`.

The image is a Node runtime, and the `NODE_COMPILE_CACHE` variable is there because cold start performance matters for a server that may be called per request.

Profiles shape the output, and introspection grades it

The command line exposes profiles that change what goes into the document and what the tool does with it. For application security, the documented invocation is:

bash
cdxgen -o bom.json --profile appsec --evidence --bom-audit .

The profile adds evidence to the BOM and runs BOM audit rules, and the documentation frames the next step as feeding the result into downstream security workflows.

The build engineer profile is more interesting, because it evaluates the generator itself:

bash
cdxgen --profile introspect --introspect-fail-below 70 -o bom.json .

That grades how completely the SBOM captured the project, and the documentation says it produces ranked fixes when the build environment degraded the result. The threshold is a score below which the run fails. The idea is that a BOM which quietly lost half its dependencies because the build environment was incomplete is worse than no BOM, because downstream tools treat a present document as a complete one.

The hardware path has a matching set of safety valves. `hbom --dry-run` produces a read-only partial HBOM plus an exact list of blocked hardware probe commands, so you see what will not be collected before a full run. `hbom diagnostics` reports missing native utilities and permission denied enrichments, which is the question to ask before deciding to install host packages or rerun with `--privileged`. That last one is a real decision point, since privileged collection on a host is not something to enable by default.

A generator, not a vulnerability scanner

The clearest boundary in the documentation is the vulnerability disclosure report. The project states that a VDR is produced by using cdxgen with OWASP depscan to automate the generation of VDR at scale. cdxgen supplies the inventory, and the scanning tool supplies the findings. If your requirement is a list of known vulnerable dependencies with severities, cdxgen alone is the wrong tool, because it is not the component that knows which versions are affected.

The second boundary is the platform coverage for the hardware and operations documents. The supported live hosts are named as Apple Silicon macOS and Linux amd64 and arm64 systems, and the operations BOM is for Linux container images and VMs running Linux or Windows. There is no listed support for other hardware platforms, and `hbom diagnostics` exists precisely because some of those probes are unavailable on some hosts.

A third limit is worth naming because it is easy to misread the screenshots: the AI/ML BOM is described as a catalogue of prompt files, AI services, MCP configs and model metadata with findings attached. That is an inventory with analysis, and it is a different artifact from a model's weights, evaluation results or training data provenance. If you need those, this document is not them.

Apache-2.0, a v12 line still shipping, and a v13 migration guide

The licence is Apache-2.0, stated in the `package.json`, in the `pyproject.toml`, and in the `LICENSE` file at the repository root, and the compose file repeats it in the image annotations.

On versions, the release history is dense and slightly awkward. v13.4.0 and v12.8.6 were both published on 2026-10-14, v13.3.0 on 2026-10-02, and the last push to the repository was on 2026-10-15. Two lines are being maintained at once, and the repository contains a `MIGRATING-TO-V13.md` file, which is the signal that a v12 to v13 move is a real upgrade with breaking changes rather than a routine bump.

The manifests are ahead of the tags in one respect: both `package.json` and `pyproject.toml` already declare version 13.5.0, while the newest published release tag is v13.4.0. So the version in the source tree is the one in development.

The Python side of the project is the packaging helper rather than the tool itself, with `pyproject.toml` describing it as managing Python dependencies for cdxgen and depending on atom-tools, blint and custom-json-diff, requiring Python 3.10 or newer, and classified as Private :: Do Not Upload, meaning the Python package is not published to a public index. The npm package is `@cdxgen/cdxgen`, and the project also ships a JSR entry, a Deno configuration, and a `deno.json`, which is a sign that the runtime reach is wider than Node alone.

Editorial conclusion

cdxgen fits a build or release team that has to emit a machine-readable inventory of what is inside a project or image, that needs the CycloneDX format rather than a bespoke report, and that wants the same generator available as a library, a REPL and a long running server. It does not fit a team looking for vulnerability findings, since a vulnerability disclosure report is produced by pairing cdxgen with OWASP depscan, and it is a poor fit for a project pinned to a single old CycloneDX consumer, because the tool targets 1.6, 1.7 and 2.0 and only downgrades to 1.4 and 1.5. Before you wire it into CI, check which major line you adopt, since a v13 migration guide exists in the repository and both a v12 and a v13 release were published on 2026-10-14.

Frequently asked questions

How do I generate an SBOM for a project with cdxgen?

Run `cdxgen -o bom.json .` against a local path, a git URL, a purl or a container image, and the tool writes a CycloneDX JSON BOM. The output targets CycloneDX 1.6, 1.7 and 2.0, and can be downgraded to 1.4 or 1.5 for legacy consumers.

Can cdxgen produce SPDX output?

Yes. SPDX 3.0.1 JSON-LD export is supported through `cdxgen --format spdx` or through the separate cdx-convert tool. CycloneDX JSON remains the primary native format.

Does cdxgen find vulnerable dependencies?

No. cdxgen is the inventory generator, and the documentation states that a vulnerability disclosure report is produced by using cdxgen with OWASP depscan to automate the generation of VDR at scale. Vulnerability findings come from the scanning tool, not from cdxgen.

How do I run cdxgen as a server?

The server mode is started with `cdxgen --server --server-host 0.0.0.0 --server-port 9090`, and the repository ships a docker-compose.yml that builds the image from ./ci/Dockerfile, publishes port 9090 and mounts your sources directory to /app. Environment variables include FETCH_LICENSE and CDXGEN_DEBUG_MODE.

What is the difference between the appsec and introspect profiles?

The appsec profile, used as `cdxgen -o bom.json --profile appsec --evidence --bom-audit .`, enriches the BOM with evidence and runs audit rules. The introspect profile grades how completely the SBOM captured the project and can fail the run below a threshold, for example with `--introspect-fail-below 70`.

Which Python and Node versions does cdxgen need?

The Python packaging helper in pyproject.toml requires Python 3.10 or newer and is classified as Private :: Do Not Upload, so it is not published to a public index. The main tool is published to npm as @cdxgen/cdxgen, and the repository also ships a JSR entry and a deno.json for Deno.

Official sources

  1. cdxgen/cdxgen on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cdxgen-cdxgen.svg)](https://hysenlabs.com/projects/cdxgen-cdxgen)

Was this useful?