55. Supply chain: Cargo.lock, cargo audit, cargo deny, build.rs
A typical Axum service has 150 to 300 transitive dependencies. Each one is
code you run, and some run at build time: build.rs scripts and
procedural macros execute on the developer's laptop and in CI with full
access to the filesystem and network. That is the main supply-chain risk
specific to Rust
(Security from Zero Ch 47,
Security in Depth Ch 12–13).
55.1 The controls, in the order to adopt them
# 1. Reproducible resolution: commit Cargo.lock, and make CI fail if it would change.
cargo build --locked
# 2. Known vulnerabilities, from the RustSec advisory database.
cargo install cargo-audit && cargo audit
# 3. Policy: advisories + licenses + banned crates + duplicate versions + allowed sources.
cargo install cargo-deny && cargo deny init && cargo deny check
# 4. See what you actually pull in, and why.
cargo tree -e features -i openssl-sys # who enables this crate?
cargo tree -d # crates present in more than one version
# 5. Human review of third-party code, recorded and shared: cargo-vet (Mozilla, Google).
cargo install cargo-vet && cargo vet init
A starting deny.toml:
[advisories]
version = 2
yanked = "deny" # yanked versions usually mean "do not use"
[licenses]
version = 2
allow = ["MIT", "Apache-2.0", "BSD-3-Clause", "ISC", "Unicode-3.0", "Zlib"]
[bans]
multiple-versions = "warn"
deny = [{ name = "openssl", reason = "use rustls" }]
[sources]
unknown-registry = "deny"
unknown-git = "deny" # no surprise git dependencies
55.2 Habits that reduce exposure
- Turn off default features you do not use:
reqwest = { version = "0.13", default-features = false, features = ["json", "rustls"] }. Fewer features means fewer crates and less build-time code. - Watch for typosquatting when you run
cargo add. Check download counts, the repository link, and the owners on crates.io. Malicious crates imitating popular names have been published and removed several times. - Pin and verify CI tools (
cargo install --locked --version x.y.z), just like dependencies. - Sandbox builds of untrusted code, in a container with no secrets and
no network after
cargo fetch. - Prefer pure-Rust crates where they are mature (
rustlsoveropenssl), which removes a C toolchain and a C attack surface from the build.
The Go guide's equivalent is
govulncheck in §64.
One difference: govulncheck checks whether your code actually calls the
vulnerable function, while cargo audit reports any vulnerable crate
version in your lockfile. Expect more findings from cargo audit, and
triage them.