With the CycloneDX Maven plugin, the SBOM is attached as an extra artifact with the classifier cyclonedx during install or deploy. It is published beside your jar under a predictable name, so anyone with repository access can fetch the SBOM for an exact version.
What gets attached
By default the plugin attaches its output as additional artifacts, in xml and json, named after the project and version:
artifactId-version-cyclonedx.xml
artifactId-version-cyclonedx.json
This follows Maven's classifier convention, the same mechanism used for sources and javadoc jars. Because the SBOM sits at the same coordinates as the jar plus a classifier, it is tied to a specific release and cannot drift to a different version.
Why publishing beside the artifact helps
Consumers of a library often want to know what it pulls in without building it. A published SBOM answers that from the repository itself. Auditors, customers and your own downstream teams can retrieve the file for the exact version they run.
It also solves the "which SBOM goes with which release" problem. When the file lives next to the artifact, the mapping is built in. Compare that with a file emailed in a thread, where the link to a version lives only in someone's memory.
Setting it up
Add the plugin to the build with the aggregate goal bound to the package phase, as the README shows:
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>makeAggregateBom</goal>
</goals>
</execution>
</executions>
</plugin>
Then run your normal install or deploy. The plugin has three goals: makeBom for each module, makeAggregateBom for the whole multi-module build, and makePackageBom for war and ear modules.
Controls you should know
| Property | Effect |
|---|---|
| cyclonedx.skipAttach | Set to true to stop attaching the SBOM as an artifact |
| cyclonedx.classifier | Change the classifier name |
| cyclonedx.skip | Set to true to skip a goal entirely |
You can still write the file to the build directory with attaching off, which is handy if you want to sign or process it before deciding where it goes.
Decisions before you publish
- Is the repository public? If so, the SBOM becomes public too. Check that component names, internal module names and any metadata you added are acceptable to share.
- Which scopes are included? By default test scope is excluded, which usually suits a published file.
- Which goal fits? A library with one module wants makeBom. A multi-module application usually wants the aggregate.
- Is the file signed or checksummed alongside it? Repositories commonly publish checksums for attached artifacts, which lets a reader detect corruption, though a checksum from the same place is not the same as a signature.
Publishing an SBOM does not make it accurate. Validate the file and compare its component list with what you expect before the release goes out.
Where this stops
An attached SBOM describes the build's resolved dependencies at the time. It will not mention vulnerabilities found later, so consumers should rescan the file against fresh advisory data. Safeguard can ingest an SBOM like this and keep matching it against new advisories through its SBOM and dependency scanning, and there is a free scan to try.
Quick check
Will the SBOM be deployed during mvn package?
No. Attached artifacts are published when the build reaches install or deploy. The file is still written to the build directory at the package phase.
Can I attach only the json file?
The output format option controls which formats are produced. Check the plugin documentation for the setting that restricts it.
Sources
Last reviewed: 19 October 2026.