Software Supply Chain Security

Crates.io Security Audit Results: The State of Rust Package Security

Security audits of the Rust crate ecosystem reveal patterns of unsafe code, build script risks, and supply chain vulnerabilities. Here is what the data shows.

Alex
Security Researcher
6 min read

Rust's safety guarantees are a major selling point, but the crate ecosystem introduces risks that the language itself cannot prevent. Security audits of crates.io -- both automated scans and manual reviews -- paint a nuanced picture. Rust packages are generally better than other ecosystems in some areas, but they face the same supply chain challenges as everyone else.

The Rust Security Response Working Group, the cargo-audit tool, and community efforts like cargo-crev provide data on the security posture of the crate ecosystem. Here is what those sources tell us.

The RustSec Advisory Database

The RustSec Advisory Database is the primary source of vulnerability information for Rust crates. Maintained by the Rust Secure Code Working Group, it contains advisories for crates with known security issues, including memory safety bugs, logic errors, and supply chain concerns.

As of early 2024, the database contains several hundred advisories spanning categories like memory safety violations in unsafe code, soundness issues that allow safe code to trigger undefined behavior, denial of service through resource exhaustion, and information disclosure through timing side channels.

The advisory rate for Rust crates is lower than comparable ecosystems (npm, PyPI), but this partly reflects the smaller ecosystem size and the higher barrier to entry for Rust development. It does not mean Rust crates are immune to security issues.

Unsafe Code Prevalence

Rust's unsafe keyword allows developers to bypass the compiler's safety guarantees. While unsafe is necessary for some operations (FFI, hardware access, performance-critical code), it is also where most memory safety bugs in Rust occur.

Studies of the crate ecosystem show that approximately 20-30% of published crates use unsafe code directly. When transitive dependencies are included, the percentage of projects that depend on some unsafe code approaches 100% -- the standard library itself uses unsafe extensively.

The security concern is not that unsafe exists, but that auditing unsafe code requires expertise that most developers do not have. A crate that exposes safe APIs built on unsafe internals can have soundness bugs that allow safe code to trigger memory corruption.

Build Script Risks

As discussed in other contexts, Rust build scripts (build.rs) run arbitrary code during compilation. A survey of popular crates shows that roughly 25% of crates with more than 1000 downloads have build scripts. Most are for legitimate purposes (compiling C dependencies, generating code), but the lack of sandboxing means a compromised build script has full access to the build environment.

The cargo-audit tool checks for known vulnerabilities but does not analyze build script behavior. Manual review remains the only way to assess build script safety, and community code review through cargo-crev is still in early adoption.

Supply Chain Findings

Several patterns emerge from supply chain analysis of crates.io:

Single-maintainer crates. A significant portion of popular crates are maintained by a single developer. If that developer's account is compromised, or if they become unavailable, the crate's supply chain security is at risk. The Rust community has discussed crate-level multi-maintainer requirements but has not implemented them.

Dependency depth. Rust projects tend to have deep dependency trees. A typical web application built with Actix or Axum might depend on 200-400 crates. Each crate is a potential attack surface.

Version churn. Crates with frequent releases create more opportunities for malicious updates to go unnoticed. Automated dependency update tools like Dependabot make this worse by creating update PRs that developers may merge without review.

Yanked crate versions. Crates.io allows version yanking but does not delete the crate data. Yanked versions remain available to existing lock files, which means security-critical yanks may not reach all affected users.

cargo-audit Effectiveness

The cargo-audit tool is the primary automated security checking tool for Rust projects. It compares your Cargo.lock against the RustSec Advisory Database and reports any dependencies with known vulnerabilities.

Limitations of cargo-audit include the fact that it only catches known, reported vulnerabilities. Zero-day issues and unreported bugs are invisible to it. It does not analyze code quality, unsafe code usage, or build script behavior. It also does not verify crate integrity or detect supply chain attacks like dependency confusion.

Despite these limitations, cargo-audit should be part of every Rust project's CI/CD pipeline. It is fast, has no false positives (it only reports confirmed advisories), and catches issues that would otherwise require manual monitoring of security mailing lists.

cargo-crev and Community Review

The cargo-crev project enables community-driven code review for Rust crates. Developers publish cryptographically signed reviews of crate versions, creating a web of trust for the crate ecosystem.

In practice, cargo-crev adoption remains low. The effort required to review a crate thoroughly is significant, and the network of reviewers is small relative to the number of published crates. However, for high-security projects, cargo-crev provides a framework for systematic dependency review that does not exist in most other ecosystems.

Recommendations for Rust Teams

Run cargo-audit in CI/CD. This is the minimum viable security check. It is free, fast, and catches known issues.

Minimize dependencies. Every crate in your dependency tree is an attack surface. Evaluate whether each dependency is necessary. Rust's standard library is comprehensive enough that many small utility crates can be replaced with a few lines of code.

Audit unsafe code in critical dependencies. For dependencies in your security-critical path, review the unsafe code blocks. Tools like cargo-geiger can quantify unsafe code usage across your dependency tree.

Pin dependency versions. Use exact version pins in Cargo.toml for direct dependencies. Use Cargo.lock in version control for applications (not libraries) to ensure reproducible builds.

Monitor the RustSec advisory database. Subscribe to notifications for advisories affecting your dependencies. Do not rely solely on cargo-audit runs -- some advisories require immediate action.

How Safeguard.sh Helps

Safeguard.sh integrates with your Rust build pipeline to provide continuous security monitoring beyond what cargo-audit offers. The platform tracks dependency changes, monitors crate ownership and publishing patterns, detects anomalous build script behavior, and generates comprehensive SBOMs for your Rust projects. By combining automated vulnerability scanning with supply chain integrity verification, Safeguard.sh provides the defense-in-depth that Rust projects need.

Never miss an update

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