Before adding an SBOM generator to CI, check four things: the build tool version, the language runtime it runs on, the schema it emits, and whether it reads a lockfile or an installed tree. The open source CycloneDX generators publish minimum versions, and an older build image may fall short.
Why this fails in practice
SBOM generation is usually added late, to a pipeline that has been stable for years. The CI image might carry an older Node.js, an old Gradle wrapper or a Python from an earlier era. The generator then fails on its first run, and the failure gets blamed on "SBOM tooling" instead of a version gap.
A ten minute check up front avoids a red build and a lost afternoon.
Published minimums
These come from each project's README at the time of review. Re-check them, because they move.
| Generator | Runtime or tool requirement |
|---|---|
| CycloneDX Gradle plugin 3.x | Gradle 8.4 or newer; build JVM Java 8 or newer, with versions before Java 17 deprecated |
| CycloneDX npm tool | Node.js 20.18.0 or newer and npm 9 or newer |
| CycloneDX Python tool | Python 3.9 or newer, below 4 |
| CycloneDX gomod tool (building from source) | Go 1.26 or newer; prebuilt binaries are also offered |
The Gradle README adds that the plugin is tested on Java 8, 11, 17, 21 and 25, and that the JVM which can run a build also depends on Gradle's own Java compatibility matrix.
Older generator releases exist for older runtimes. The npm README says earlier versions of the tool support Node.js 14 and npm 6, and the Python README says older versions support Python 2.7. Those older releases emit older schema versions and miss newer features, so use them only when you cannot upgrade the build image.
The compatibility checklist
- Print the versions your CI image actually uses: the build tool, the language runtime and the package manager.
- Compare each against the table above and the current README.
- Decide per gap: upgrade the image, run the generator in a separate job on a newer image, or use an older generator release.
- Run the generator once on a branch before it is required by anything.
- Record the generator version in the build log so the SBOM can be reproduced.
Option two is often the cheapest. Generating an SBOM does not require running the build itself on the same image, provided the generator reads the same dependency inputs. Be careful though: for npm, the tool reads the installed tree by default, so the install must happen in that job too.
Lockfile or installed tree
Generators differ in what they read. The npm tool can use only the lockfile via an option, or read the installed packages on disk. Reading installed packages gives richer data but needs a completed install. The Python tool can read a virtual environment, a Poetry or Pipenv project, or a requirements file. Decide which fits your pipeline and check that the inputs exist at the point where the job runs.
What a pass looks like
A passing check means the job exits cleanly, produces a file, and the file validates against the schema it claims. Then compare the component count with what you expect from your lockfile. A count of zero or a tiny count usually means the generator found no inputs.
Safeguard can read the resulting file and the dependency manifests behind it through its SBOM and dependency scanning, and a free scan is a quick way to see whether your output is picked up.
Quick check
Do I need to upgrade my whole build to generate an SBOM?
Not always. You can run the generator in a separate job on a newer image, as long as it has the same dependency inputs available.
Where do I find the current minimum versions?
In each generator's README and release notes. They change between releases, so check them when you pin a version.
Sources
- CycloneDX Gradle plugin README
- CycloneDX npm tool README
- CycloneDX Python tool README
- CycloneDX gomod README
Last reviewed: 19 October 2026.