We conducted an analysis of CycloneDX and Dependency-Track toolchain support for the Rust language and ecosystem, with the following questions:
Rust is very well supported by the available tools, and provides 100% coverage of production dependencies. Development and build dependencies are not fully supported, which will be explained later in this analysis.
This was tested by creating CycloneDX files of the following major Rust projects from source, and importing the CycloneDX file in Dependency-Track:
I also created a custom project to test the CycloneDX build commands.
https://github.com/VioletBeacon/violetbeacon_deptrack_testproject_rust_cargo
The most reliable way to generate a CycloneDX BOM is with the following sequence:
# Install cargo-cyclonedx (only needs to be run once) $ cargo install cargo-cyclonedx # Build CycloneDX file $ ~/.cargo/bin/cargo-cyclonedx cyclonedx -f json --spec-version 1.5 \ --all --target all
If the project includes multiple packages, you have a choice: You can either upload each BOM file individually to Dependency-Track as separate projects, or merge all the BOMs for the project together.
To merge them together, you can use cyclonedx-cli:
# Install the latest cyclonedx cli from https://github.com/CycloneDX/cyclonedx-cli # Adjust the version number and path as desired (this is just an example) $ sudo wget https://github.com/CycloneDX/cyclonedx-cli/releases/latest/download/cyclonedx-linux-x64 \ -O /usr/local/bin/cyclonedx $ sudo chmod 0755 /usr/local/bin/cyclonedx # Merge all .cdx.json files together $ cyclonedx merge --input-files `find . -name "*.cdx.json"` \ --output-file [outputfile]
To upload the BOM to Dependency-Track, you'll need an API Key.
The VioletBeacon Dependency-Track client makes uploading the BOM much easier than using the CURL commands that are documented in the Dependency-Track documentation.
# Install the VioletBeacon Dependency-Track Client $ pip install violetbeacon-deptrack-client # 1. Set the DTRACK_APIKEY environment variable in your CI/CD environment # 2. Set the DTRACK_BASEURL environment variable in your CI/CD environment $ deptrack-client upload-bom -a -p [PROJECT] -q [VERSION] -f [bom.cdx.json]
If the dependency is a production dependency and listed in Cargo.toml, then it will get added to the CycloneDX file.
If the dependency is a dev dependency, then it will not get added to the CycloneDX file.
If the dependency is a transitive production dependency and is included in Cargo.lock during a 'cargo' operation (cargo build, etc.), then it will get added to the CycloneDX file.
Build and dev dependencies currently do not get added to the CycloneDX file.
If a dependency is not listed in the CycloneDX file, it will not be analysed by Dependency-Track.
So, at this point, there is 100% coverage of Rust production dependencies, but 0% coverage of dev or build dependencies.
In the violetbeacon_deptrack_testproject_rust_cargo GitHub repo is a concrete example that we created.
This project includes futures-core, smallvec, tokio and idna as dependencies. We built the project and inspected which dependencies were downloaded. We then cleared the cargo cache and generated the CycloneDX BOM file and inspected which dependencies were downloaded and which were listed in the CycloneDX BOM. The results were compared and are included in the dependency_comparision.ods file in the repo.
The sequence of commands that we ran is in the Makefile and can be run using make
.
Below are the results of the analysis. You'll notice that CycloneDX and Dependency-Track provides more complete
coverage than cargo-tree. This is due to cargo cyclonedx
being called with the
--target all
option, which includes all dependencies for all possible targets.
Cargo.lock crates | CycloneDX output | CycloneDX --all-features output | Crates downloaded during CycloneDX run | Crates downloaded during CycloneDX --all-features run | CycloneDX default target | CycloneDX default target crates downloaded | CycloneDX --target all | CycloneDX --target all downloads | Crates downloaded during cargo build | cargo tree | CycloneDX --all-features in Dependency-Track |
---|---|---|---|---|---|---|---|---|---|---|---|
addr2line | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
adler2 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
autocfg | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
backtrace | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
bitflags | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
bytes | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
cfg-if | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
futures-core | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
gimli | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
hermit-abi | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
idna | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
libc | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
lock_api | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
memchr | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
miniz_oxide | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
mio | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
num_cpus | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
object | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
parking_lot | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
parking_lot_core | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
pin-project-lite | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
proc-macro2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
quote | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
redox_syscall | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
rustc-demangle | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
scopeguard | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
signal-hook-registry | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
smallvec | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
socket2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
syn | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
tinyvec | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
tinyvec_macros | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
tokio | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
tokio-macros | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
unicode-bidi | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
unicode-ident | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
unicode-normalization | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
violetbeacon_deptrack_testproject_rust_cargo | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ |
wasi | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
windows_aarch64_gnullvm | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
windows_aarch64_msvc | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
windows_i686_gnu | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
windows_i686_gnullvm | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
windows_i686_msvc | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
windows-sys | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
windows-targets | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
windows_x86_64_gnu | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
windows_x86_64_gnullvm | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
windows_x86_64_msvc | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
Dependency-Track looks up vulnerabilities from the following vulnerability databases, if they are enabled in the Dependency-Track configuration:
cargo audit
only retrieves advisories from the GitHub Advisory Database.
cargo audit
identified the same vulnerability in idna 0.5.0 (CVE-2024-12224/RUSTSEC-2024-0421), and an
INFO warning for tokio 1.31.0 (RUSTSEC-2025-0023).
cargo update
only identified redox_syscall
for update.
Crate referenced in Cargo.lock | Dependency-Track | cargo audit | cargo update |
---|---|---|---|
futures-core 0.3.6 | Upgrade to 0.3.31 | - | - |
idna 0.5.0 | 1 HIGH vuln, Upgrade to 1.0.3 | Upgrade to >=1.0.0 | - |
smallvec 1.6.1 | Upgrade to 1.15.1 | - | - |
tokio 1.31.0 | Upgrade to 1.46.1 | Info only. No solution. | - |
Crate referenced in Cargo.lock | Dependency-Track | cargo audit | cargo update |
---|---|---|---|
addr2line 0.24.2 | Upgrade to 0.25.0 | - | - |
futures-core 0.3.6 | Upgrade to 0.3.31 | - | - |
gimli 0.31.1 | Upgrade to 0.32.0 | - | - |
mio 0.8.11 | Upgrade to 1.0.4 | - | - |
object 0.36.7 | Upgrade to 0.37.1 | - | - |
redox_syscall 0.5.13 | Upgrade to 0.5.15 | - | Upgrade to 0.5.15 |
socket2 0.5.10 | Upgrade to 0.6.0 | - | - |
tokio-macros 2.1.0 | Upgrade to 2.5.0 | - | - |
windows_aarch64_gnullvm 0.52.6 | Upgrade to 0.53.0 | - | - |
windows_aarch64_gnullvm 0.48.5 | Upgrade to 0.53.0 | - | - |
windows_aarch64_msvc 0.52.6 | Upgrade to 0.53.0 | - | - |
windows_aarch64_msvc 0.48.5 | Upgrade to 0.53.0 | - | - |
windows_i686_gnu 0.52.6 | Upgrade to 0.53.0 | - | - |
windows_i686_gnu 0.48.5 | Upgrade to 0.53.0 | - | - |
windows_i686_gnullvm 0.48.5 | Upgrade to 0.53.0 | - | - |
windows_i686_msvc 0.52.6 | Upgrade to 0.53.0 | - | - |
windows_i686_msvc 0.48.5 | Upgrade to 0.53.0 | - | - |
windows-sys 0.52.6 | Upgrade to 0.60.2 | - | - |
windows-sys 0.48.5 | Upgrade to 0.60.2 | - | - |
windows-targets 0.52.0 | Upgrade to 0.53.2 | - | - |
windows-targets 0.48.5 | Upgrade to 0.53.2 | - | - |
windows_x86_64_gnu 0.52.6 | Upgrade to 0.53.0 | - | - |
windows_x86_64_gnu 0.48.5 | Upgrade to 0.53.0 | - | - |
windows_x86_64_gnullvm 0.52.6 | Upgrade to 0.53.0 | - | - |
windows_x86_64_gnullvm 0.48.5 | Upgrade to 0.53.0 | - | - |
windows_x86_64_msvc 0.52.6 | Upgrade to 0.53.0 | - | - |
windows_x86_64_msvc 0.48.5 | Upgrade to 0.53.0 | - | - |
Note: The windows*
dependencies which are shown in the CycloneDX BOM and Dependency-Track but not in
cargo audit/update
are transitive production dependencies that are referenced in multiple crates. As an
example, windows_x86_64_msvc
is highlighted in green in the screenshot below.
Using the VioletBeacon Dependency-Track Client makes integration with CI/CD pipelines simple by following these steps:
1. The following environment variables must be set in the pipeline:
DTRACK_BASEURL
DTRACK_APIKEY
2. Shell command-based integration can be done with the following steps:
# Build SBOM $ cargo install cargo-cyclonedx $ ~/.cargo/bin/cargo-cyclonedx cyclonedx -f json --spec-version 1.5 \ --all --target all # Upload SBOM $ pip install violetbeacon-deptrack-client $ deptrack-client upload-bom -a -p [PROJECT] -q [VERSION] \ -f [bom.cdx.json]
An error in cargo-cyclonedx or deptrack-client will return a non-zero result.
If any quality gates are desired, these can be implemented via the Dependency-Track API or using Rust's
cargo audit
.