Safeguard
Developer Tools•

How do you link an SBOM to the CI build that produced it?

Add a build reference to each SBOM so readers can trace it to the exact CI job. The CycloneDX Gradle plugin detects several CI systems for you.

Safeguard Security Team
4 min read

Record a build system reference inside the SBOM, a URL that points to the CI job that created it. The CycloneDX Gradle plugin can do this automatically for several CI systems when includeBuildSystem is true, and lets you build a custom URL from environment variables for others.

Why bother

An SBOM file on its own says what a build contained, not where it came from. Months later someone asks which job produced it, which commit, and whether it can be trusted. If the file carries a link to the CI run, those questions have a starting point. Without one, you depend on file names and memory.

A build reference is not proof. Anyone who can edit the file can edit the link. It is a pointer that helps investigation and audit, and it complements, not replaces, signatures and provenance.

What the Gradle plugin does

According to the README, when includeBuildSystem is true the plugin automatically detects build URLs from GitHub Actions, GitLab CI, Jenkins, CircleCI, Travis CI and Drone. For anything else, buildSystemEnvironmentVariable lets you name an environment variable, or compose a URL from several.

A rule to know: every variable in a template must exist and have a non blank value, otherwise no build system reference is added. The failure is silent, in the sense that the build still succeeds and the SBOM is produced without the link.

Kotlin DSL example from the README:

tasks.cyclonedxDirectBom {
    buildSystemEnvironmentVariable = "\${CI_SERVER_URL}/jobs/\${CI_JOB_ID}"
}

To read one variable directly, set the property to its name, for example BUILD_URL.

Steps to adopt it

  1. Choose the CI system and find the variables that make up a link to a single job.
  2. Turn the build reference on in your plugin configuration.
  3. Run a build in CI, not locally, since local runs lack the variables.
  4. Open the SBOM and confirm the reference exists and the link opens the right job.
  5. Add a pipeline check that fails if the reference is missing, since the plugin will not.

Step 5 turns a silent gap into a visible one.

What else belongs next to the link

A build reference answers "which job". A good release record also holds:

ItemWhy
Commit hashIdentifies the source
Tool name and versionLets someone reproduce the output
Generation timeShows freshness
Checksum or signatureDetects later changes

The SBOM format has places for several of these, such as tool metadata and timestamps. Store the rest in your release record.

Other ecosystems

The same idea applies in Maven and npm builds, even though the plugin details differ. If your generator has no build reference setting, you can record the link in your release record next to the file, or add it as metadata in a post processing step. If you edit the file after generation, document the step and keep the original, since an SBOM that has been changed needs an explanation.

What to avoid

Do not put secrets or internal hostnames you would not share in a link. If the SBOM goes to customers, a CI URL on an internal domain tells them nothing and reveals a hostname. Decide whether the shared copy should carry the link or whether it stays in your internal copy.

Safeguard's SBOM and dependency scanning keeps each SBOM with its inventory and findings, and the free scan is a way to see how a file is read.

Quick check

Does the reference prove who built the file?

No. It is a pointer for tracing. Use signatures and build provenance for stronger assurance.

Why is my build reference missing?

Likely a variable in the template is unset or blank, or the build ran locally. The plugin adds no reference in that case.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.