Safeguard
Open Source Security

Rust supply chain security landscape

Rust's crates.io has topped 170,000 packages and real attacks are following. Here's what's changed and how security teams should respond.

Safeguard Research Team
Research
7 min read

Rust's crates.io registry has quietly become one of the largest unvetted code-distribution networks on the internet — north of 170,000 published crates, more than 100 billion downloads served, and thousands of new crates published every week. That growth trajectory, once a story about developer experience and memory safety, is now increasingly a story about attack surface. As Rust has moved from hobbyist systems programming into the Linux kernel, AWS's Firecracker hypervisor, Android's codebase, curl, and core infrastructure at Cloudflare, Discord, and Microsoft, the crates.io dependency graph has become a target security teams can no longer treat as an afterthought.

The irony is well understood inside the Rust community: the language was designed to eliminate an entire class of memory-corruption vulnerabilities, but it does nothing to stop a malicious or compromised dependency from running arbitrary code at build time or shipping a backdoor in a .crate tarball. Supply chain risk in Rust isn't a hypothetical — it's the logical next frontier now that the memory-safety problem is substantially solved.

A Language Built for Safety, an Ecosystem Built on Trust

Rust's core value proposition — safe by default, unsafe opt-in and auditable — has made it the go-to choice for security-conscious teams rewriting C and C++ components. Cargo-geiger scans of the crates.io corpus consistently show that a meaningful share of widely used crates still contain unsafe blocks, usually for FFI bindings, performance-critical paths, or low-level system calls. That's not a knock on the ecosystem; it's a reminder that "written in Rust" is not synonymous with "risk-free." Every unsafe block, every FFI boundary, and every build script is a place where the language's guarantees stop and ordinary software risk resumes.

The bigger structural issue is trust distribution. Cargo's dependency model, like npm's and PyPI's, resolves an enormous transitive tree from a handful of direct dependencies. A typical mid-sized Rust service can easily pull in 300-plus transitive crates, many maintained by a single volunteer, many with build scripts (build.rs) or procedural macros that execute native code during compilation — before a single line of the "safe" application logic ever runs. That build-time execution model is precisely what makes Rust's supply chain meaningfully different from, and in some ways riskier than, more static package formats: a malicious crate doesn't need to wait for your code to call it. It can compromise the developer's machine or CI runner the moment cargo build resolves it.

Where the Attacks Have Actually Landed

The Rust ecosystem has already seen the attack patterns that plagued npm and PyPI arrive on schedule. In 2022, security researchers at Phylum identified a malicious crate, rustdecimal, deliberately typosquatting the popular rust_decimal library. The package shipped a post-install shell script that attempted to harvest SSH keys and browser credential stores from developer machines — a textbook credential-theft payload delivered through nothing more exotic than a one-character name collision and a build script most developers never think to inspect.

That incident wasn't an outlier; it was a preview. Typosquatting, dependency confusion, and maintainer-account takeovers are now recurring findings in independent scans of crates.io by firms tracking open source supply chain abuse, mirroring the same techniques that have hit event-stream on npm, ctx and phpass on PyPI, and dozens of other registries. Rust's comparative youth as a mainstream ecosystem has so far limited the blast radius, but the RustSec Advisory Database — the community-maintained clearinghouse for known vulnerabilities in published crates — has grown from a handful of entries at launch to several hundred tracked advisories, spanning everything from unsound API design and denial-of-service issues to full remote-code-execution flaws in parsing libraries. The trend line, not any single incident, is the story: as crates.io's economic and infrastructural importance grows, so does the incentive for attackers to plant something in it.

The Registry Is Hardening — Slowly

To its credit, the Rust project and the Rust Foundation have not been passive. Crates.io rolled out trusted publishing in 2024, allowing maintainers to authenticate CI/CD publish jobs via short-lived OIDC tokens issued by GitHub Actions instead of long-lived API tokens sitting in repository secrets — directly closing the same class of stolen-token publishing attack that hit PyPI and npm maintainers repeatedly. The registry has also tightened account security requirements, added scoped tokens, and improved crate-ownership transfer controls after several ownership-hijacking incidents made headlines in other ecosystems.

On the tooling side, the ecosystem has produced a genuinely strong set of building blocks: cargo-audit for checking dependencies against RustSec advisories, cargo-deny for enforcing license, ban, and advisory policies in CI, cargo-vet (originated at Mozilla) for recording and sharing human audit attestations across organizations, and cargo-crev for distributed, web-of-trust-style code review. The Rust Foundation's Security Initiative, staffed with dedicated security engineers since 2023, has funded fuzzing infrastructure, sponsored audits of foundational crates, and published guidance on unsafe code review practices.

Where the Gaps Still Are

None of that tooling, however, solves the two hardest problems in Rust supply chain security today.

First, known-vulnerability scanning isn't the same as risk assessment. cargo-audit will tell you that a transitive dependency has a RustSec advisory against it. It will not tell you whether your specific binary calls the vulnerable function, whether that code path is reachable from an attacker-controlled input, or whether the vulnerable feature flag is even compiled in. For a language whose entire value proposition is precision and control over what actually ships in a binary, most Rust shops are still triaging CVEs the blunt way — by dependency version number rather than by actual exploitability.

Second, build-time execution remains largely unmonitored. Unlike a JavaScript payload that fires after npm install completes, a malicious build.rs script or procedural macro executes as part of cargo build itself, often with full access to environment variables, filesystem, and network from the CI runner. Very few organizations sandbox their build environments against this risk, and static SBOM generation after the fact does nothing to catch code that already ran during compilation last Tuesday.

Third, SBOM practices for Rust binaries lag behind the ecosystem's growth. Rust's preference for static linking means a single shipped binary can bundle dozens of statically compiled dependencies with no runtime artifact trail — making accurate, automated SBOM generation (rather than manual Cargo.lock inspection) essential for anyone who needs to answer "are we affected by this new RustSec advisory" in minutes rather than days.

What Security Teams Should Take Away

The near-term risk profile for Rust supply chain security looks a lot like where npm was around 2018 and PyPI around 2020: a fast-growing registry, improving but incomplete platform-level defenses, and attacker techniques (typosquatting, maintainer takeover, malicious build scripts) that are well understood elsewhere and simply haven't been fully unleashed on crates.io yet. Organizations standardizing on Rust for security-sensitive workloads — which is an increasing number of them, precisely because of its memory-safety guarantees — should not assume the language's safety properties extend to its dependency supply chain. They don't.

Practical priorities for teams shipping Rust today: enforce cargo-deny or equivalent policy checks in CI on every merge, generate and retain a real SBOM (not just a Cargo.lock snapshot) for every release artifact, sandbox or restrict outbound network access for build environments running third-party build.rs scripts, and treat crates.io dependency updates — especially new transitive dependencies pulled in silently by a minor version bump — with the same scrutiny given to any other third-party code addition.

How Safeguard Helps

Safeguard is built for exactly this gap between "we have a dependency scanner" and "we know what's actually exploitable." Our reachability analysis traces whether a vulnerable function in a Rust crate — including in transitive dependencies pulled in through Cargo's resolution graph — is actually reachable from your application's entry points, cutting through advisory noise to surface the handful of findings that matter. Griffin AI layers on top of that analysis to reason about exploitability, prioritize fix order, and explain the attack path in plain language for engineering teams who don't have time to read every RustSec entry. Safeguard generates and ingests accurate SBOMs directly from Cargo.lock and compiled binaries, so teams have a real-time, auditable inventory instead of a point-in-time snapshot that's stale by the next release. And when a fix is available, Safeguard opens auto-fix pull requests that bump the affected crate and its transitive chain correctly, so remediation doesn't sit in a backlog while the exploit window stays open.

Never miss an update

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