In May 2022, a Rust developer noticed something odd: a crate called rustdecimal, freshly published to crates.io, was drawing more attention than its download count justified. It wasn't a coincidence. rustdecimal was a near-perfect typo of rust_decimal, a decimal-arithmetic crate used in financial and data-processing code across the Rust ecosystem. The malicious crate's build script quietly downloaded a second-stage payload built to steal credentials from Windows and Linux machines the moment a developer ran cargo build. This is crates.io typosquatting in practice — attackers exploiting the trust developers place in familiar package names to slip malicious code straight into the build pipeline. As Rust adoption grows in systems programming, blockchain, and infrastructure tooling, crates.io has become a real target, and understanding how these attacks work is now a baseline requirement for any team shipping Rust code.
What Is Crates.io Typosquatting?
Crates.io typosquatting is the practice of publishing a malicious or low-quality crate under a name deliberately chosen to be confused with a popular, trusted one — a single transposed letter, an added hyphen, a missing underscore, or a plausible-sounding synonym. Because cargo add and Cargo.toml entries are just text, a developer who fat-fingers serde_json as serdejson, or copies a dependency name from a blog post with a typo already baked in, can pull in an attacker-controlled package without any warning from the toolchain.
Crates.io has one structural defense most other registries lack: it normalizes crate names so that hyphens and underscores are treated as equivalent when checking uniqueness, which closes off the single most common typosquat trick used against npm and PyPI. But it doesn't stop character-swap typos, prefix or suffix additions (rust-decimal-utils), or names that mimic a crate's description rather than its exact spelling. Combined with Rust's culture of small, single-purpose crates — the average dependency tree for a nontrivial Cargo project can run to 200-500 transitive crates — the attack surface for a convincing typosquat is large, and most of it is invisible to a developer skimming a Cargo.toml diff.
How Did the Rustdecimal Incident Show the Real Cost of a Malicious Rust Crate?
The rustdecimal incident, reported in May 2022, remains the clearest public example of a malicious Rust crate doing real damage rather than just sitting on crates.io as a proof of concept. The package typosquatted rust_decimal, a widely used crate for precise decimal math that financial and data-heavy applications rely on specifically because floating-point arithmetic isn't safe for money calculations. Rather than shipping malicious logic in the crate's own source, rustdecimal used a build.rs build script — code that Cargo executes automatically and unsandboxed during cargo build, before a single line of the developer's own project compiles. That script fingerprinted the host operating system and downloaded a second-stage binary designed to harvest saved credentials and browser data on both Windows and Linux.
Because build scripts run with the same privileges as the developer invoking Cargo — often a CI runner with access to secrets, cloud credentials, or signing keys — the blast radius extends well past the individual laptop that ran cargo build once. Crates.io pulled the crate after it was reported, but the incident illustrated a hard truth: in Cargo's model, simply adding a dependency to evaluate it can be enough to get compromised.
Why Is Cargo Especially Exposed to Supply Chain Attacks?
Cargo is especially exposed to supply chain attacks because two of its core features — build scripts and procedural macros — execute arbitrary native code at build time with no sandbox, no permission model, and no review gate. A build.rs file runs before compilation; a proc-macro crate runs during compilation, with the ability to read the filesystem, make network calls, or shell out to other binaries, all disguised as ordinary compile-time code generation. Most other language ecosystems have at least partially walked this back — npm's postinstall scripts and Python's setup.py are notorious for similar abuse — but neither is as deeply load-bearing to the ecosystem as build scripts and macros are in Rust, where crates like serde, tokio, and thousands of FFI bindings depend on them by design.
Layer onto that Cargo's dependency resolution: a single cargo add can pull in hundreds of transitive crates from dozens of independent maintainers, any one of whom could have a compromised account, an expired domain tied to their crates.io email, or simply decide to ship something malicious in an update. A 2023-2024 wave of malicious crates uncovered by supply-chain security researchers followed exactly this pattern — packages with innocuous names and small, useful-looking functionality that quietly exfiltrated environment variables, .env files, or SSH keys during a build step nobody thought to inspect.
What Has Crates.io Done to Improve Rust Package Registry Security?
Crates.io has shipped a steady set of rust package registry security improvements over the past few years, though several closed npm- and PyPI-style gaps only recently. In 2023, the registry began requiring a verified email address before an account can publish any crate, cutting down on disposable accounts used purely for squatting or drive-by malware drops. Crates.io also migrated its index from a git-based format to a sparse HTTP index in early 2023 (shipping alongside Cargo 1.68), which, beyond the performance win, made it far easier for security tooling to poll and diff the registry in near real time rather than cloning a multi-gigabyte git history. More recently, crates.io has been rolling out trusted publishing support, letting CI pipelines authenticate to the registry with short-lived OIDC tokens scoped to a specific GitHub Actions workflow instead of long-lived API tokens sitting in a secrets store — the same model PyPI adopted in 2023 after repeated incidents of stolen publish tokens being used to push malicious releases of legitimate packages.
None of this replaces vigilance. The RustSec Advisory Database and its cargo audit CLI tool crowdsource reports of vulnerable and malicious crates, but they are reactive by nature — a crate has to be caught and reported before it lands in the database, and crates.io now hosts well over 150,000 crates, far more than any small working group can manually review.
What Typosquatting Patterns Should Rust Developers Watch For?
Rust developers should watch for five recurring typosquatting patterns: character transposition (toko for tokio), added or dropped separators (variants of serde-json that don't match the canonical serde_json), plausible fake forks (fast-log2, xlog-rs mimicking real logging crates), suffix bait (-utils, -extra, -pro implying an official extension of a popular crate), and outright name revival — republishing under a name recently yanked or abandoned by its original maintainer. A crate with zero or near-zero GitHub stars, a publish history of a single version, a description copy-pasted from the real crate, or a maintainer account created the same day as the first publish are all red flags worth a 30-second check before running cargo add.
The most reliable defense is procedural: pin exact versions and hashes in Cargo.lock, commit that lockfile, review diffs to it in every pull request the same way you'd review application code, and treat any new transitive dependency — not just direct ones — as something that ran arbitrary code on your build machine the moment cargo build finished.
How Safeguard Helps
Safeguard is built to catch exactly this class of attack before a malicious crate ever reaches a build server. Our platform continuously monitors your Cargo.toml and Cargo.lock across every repository, flagging new or changed dependencies against known-good package identities and a live typosquat-detection model that scores name similarity, publish age, maintainer reputation, and download velocity — the same signals a human reviewer would check manually, run automatically on every pull request.
Because the real damage in Cargo attacks happens inside build scripts and proc-macros, Safeguard specifically analyzes build.rs behavior and macro-expansion side effects for network calls, filesystem access, and process execution that don't match a crate's stated purpose, rather than relying only on static vulnerability databases like RustSec. When a risky or typosquatted crate is detected, Safeguard blocks the merge, generates an SBOM entry documenting the finding, and routes an alert to your security team with the specific line in Cargo.lock responsible — so a rust_decimal-style incident gets caught in code review, not in a compromised CI runner three sprints later.