# When Your Compiler Becomes the Attacker: Rust's Supply Chain Blindspot
Three crates. One compromised account. And somewhere between cargo build and a finished binary, your development machine was calling home to a server you'd never heard of.
The Rust Project confirmed this week that it pulled malicious versions of arrayref, internment, and append-only-vec from crates.io after an attacker used a hijacked maintainer account to publish poisoned releases. The mechanism was surgical: each new version quietly introduced a typosquatted dependency — a fake crate with a name close enough to pass a casual glance — whose build.rs script reached out to a remote server and executed whatever it found there, at compile time.
These three crates collectively count somewhere north of 245 million downloads. The attack ran through the most trusted moment in a developer's workflow: the build.
## The Build Script Problem Nobody Wants to Say Out Loud
Rust's build.rs system was designed for legitimate purposes — generating bindings, compiling C dependencies, embedding version strings. But what it actually permits is arbitrary code execution with no sandboxing, no review gate, and no warning. When you run cargo build, every build.rs in your dependency tree runs with your user's privileges, on your machine, before the linker touches anything.
The Rust community has debated this for years. The ecosystem's growth has consistently won that argument.
What the attacker here understood — and what defenders consistently underestimate — is that the attack surface for a Rust project isn't the Rust code. It's the dependency graph. The typosquatting layer was a deliberate piece of misdirection: publish a crate with a name that looks like something that belongs there, wire it in as a dependency of a legitimate package via a compromised account, and let thousands of CI pipelines and developer workstations do the rest. The payload wasn't hiding in unsafe {} blocks. It wasn't exploiting memory corruption. It was just running.
## How the Hijack Worked
The entry point was a maintainer account compromise — the same weak link that's brought down npm packages, PyPI libraries, and RubyGems before this. The attacker didn't need to find a vulnerability in crates.io's infrastructure. They needed a credential. Possibly phishing, possibly a credential database leak, possibly a reused password. The specifics haven't been disclosed.
Once inside, they pushed new versions of three packages with the same owner — suggesting either one maintainer controlled all three, or the attacker moved across accounts after initial access. The malicious releases followed the semantic versioning conventions of each package without raising obvious flags: 0.3.10, 0.8.7, 0.1.9. Patch-level bumps. The kind of update that auto-merges in a Dependabot PR.
The typosquatted crate they introduced as a dependency is what carried the payload. It's a neat construction: arrayref itself looks clean at a glance; the malice lives one level down in the graph, in a crate name you'd only recognize as wrong if you were looking for it.
## What Got Hit, and What Probably Didn't
arrayref is the one that should concern you most. It's a foundational utility — the kind of crate that shows up as a transitive dependency in cryptographic libraries, parsers, and embedded systems code. People who never directly added arrayref to their Cargo.toml were still exposed if anything in their graph pulled it in.
internment and append-only-vec have narrower audiences but meaningful download counts. The payload downloaded during compilation, not at runtime — which means it ran on developer machines and CI systems, not necessarily in production containers. That distinction matters for incident response but shouldn't be mistaken for reassurance. Build environments hold secrets: API keys in environment variables, SSH credentials, cloud provider tokens, access to internal registries.
The specific scope of what the payload did — what it exfiltrated, what it executed — hasn't been fully detailed publicly. That's the part organizations with exposure need to treat as worst-case until demonstrated otherwise.
## What You Should Do Right Now
If your Rust projects depend on arrayref, internment, or append-only-vec, check your lockfiles.
arrayref 0.3.9, internment 0.8.6, append-only-vec 0.1.8cargo audit — and if you're not already running it in CI, startThe longer fix is structural. cargo-vet, Mozilla's supply chain verification tool, requires vouching for crate versions before they enter a build. It won't stop a compromised maintainer from publishing malicious code, but it stops that code from silently entering your builds without a human review step. Facebook's cargo-deny offers a lighter version of the same concept. Neither is a silver bullet, but both add friction that would have surfaced this.
---
## HackWire Analysis
This attack is a clean case study in what "supply chain security" actually means in practice — and why the ecosystem you choose doesn't protect you the way you think it does.
Rust occupies a peculiar position in security conversations. Developers reach for it specifically for safety properties: no buffer overflows, no use-after-free, no data races by default. Enterprise security teams greenlight Rust codebases with a level of trust they'd never extend to C or Python. That trust is real and mostly earned — for the code Rust developers write.
But the build pipeline is a different problem entirely, and it's one Rust hasn't solved. The build.rs execution model predates widespread supply chain attack sophistication. In 2024 and 2025, we've watched the npm ecosystem get hit repeatedly via compromised maintainer credentials. PyPI has had similar waves. The pattern is consistent: attackers don't need to outcode your language's type system. They need one set of valid credentials to the registry.
What makes the Rust case sharper is who writes Rust code. Security tooling. Cryptographic libraries. Embedded systems and firmware. Infrastructure software. The population of projects with Rust dependencies skews heavily toward environments where a covert execution during build would be maximally valuable to an attacker. The blast radius here wasn't random.
The crates.io team responded quickly once the issue was reported. That matters. But detection came after publication, not before — which means the window was open long enough for the malicious versions to propagate into locked dependency files across the ecosystem.
The real lesson isn't that Rust failed. It's that no language makes you immune to supply chain attacks, and the projects that treat language choice as a security control are the ones most surprised when this happens.
— HackWire Editorial
---
## Related Coverage