At 07:15 UTC on 20 August, someone published arrayref 0.3.10 to crates.io. It was live for 86 minutes, picked up about 2,285 downloads, and every single one of them executed attacker-controlled code on the machine doing the build. That code ran before a single line of the project itself had compiled.
arrayref has 250,376,732 lifetime downloads. Fewer than 10% of its normal daily installs touched the poisoned version. The reason is unglamorous and worth sitting with: most teams had a Cargo.lock pinning 0.3.9, so Cargo never went looking for anything newer.
Six days later the Rust Project announced its first Maintainers in Residence, directing $350,000 at six people for at least twelve months. Both stories landed in the same week, both are about who keeps Rust standing up, and the gap between them is the thing I want to talk about. As a fintech developer who has shipped Rust into payment systems, my read is that the funding is genuinely good and does almost nothing about the attack that preceded it.
What Actually Ran on Those Build Machines
The mechanics are worth spelling out, because most coverage stopped at "malicious crate."
The compromised arrayref 0.3.10 did not contain malware. It added one line to its manifest:
[dependencies.proc-macro1]
version = "1.0.107"
proc-macro1 is a typosquat of proc-macro2, one of the most-depended-on crates in the ecosystem. The real payload lived in proc-macro1-1.0.107/build.rs. Because Cargo compiles and runs build scripts for every crate in the graph, it never mattered that arrayref didn't call a single function from it. Resolving the dependency was enough to detonate.
The build script reassembled its command-and-control address from base64 fragments (23.254.165.112, port 9089 for the payload, 443 for the beacon), then installed a certificate verifier that returned success for everything it was shown. That let it pull a binary over TLS from a raw IP with a self-signed certificate without a warning. It selected a platform-specific payload (rust-crate_0.1.0 for Linux x86_64 through rust-crate_0.4.0 for macOS ARM64), wrote it to /tmp/rust-setup, chmoded it, and spawned it detached with all streams sent to null.
The Windows path is the part that tells you these people had done this before. Cargo puts child processes in a job object, so they die when the build finishes. The attacker wrote a PowerShell script to %TEMP%\rust-setup.ps1 and launched it through a VBScript wrapper under wscript.exe with CREATE_NO_WINDOW. The comment in the source said it plainly: this escapes Cargo's job object. The process outlives the build.
Read the full article on tomcn.uk →
About the Author
I'm Tom Wang, an AI Developer & Fintech Developer — building AI agents, crypto payment infrastructure, and cross-border payout systems with Rust, Go, and TypeScript. Based in London, UK.
Currently open to new opportunities in fintech, crypto payments, and AI agent engineering.
Top comments (0)