Rust Supply Chain Attack Puts Build-Time Malware in Crates with 245 Million Downloads
A compromised Rust maintainer account published malicious versions of three widely used crates (arrayref, internment, append-only-vec) that injected a typosquatted dependency (proc-macro1) with a build-time malware payload The attack exploited Cargo's build script execution model, requiring no direct usage of the compromised crate—simply building a dependent project was sufficient to trigger the payload The malicious build script disabled TLS validation, installed a stage-2 implant that beaconed
Analysis
TL;DR
- A compromised Rust maintainer account published malicious versions of three widely used crates (arrayref, internment, append-only-vec) that injected a typosquatted dependency (proc-macro1) with a build-time malware payload
- The attack exploited Cargo's build script execution model, requiring no direct usage of the compromised crate—simply building a dependent project was sufficient to trigger the payload
- The malicious build script disabled TLS validation, installed a stage-2 implant that beaconed to a C2 server, persisted across platforms, and stole browser credentials from Chrome, Brave, and Edge
- The compromised arrayref crate had accumulated over 245 million downloads with 403 dependent crates, making this one of the most impactful supply chain attacks in the Rust ecosystem
- The Rust Security Response Team removed the malicious versions within 86-107 minutes, but no patched versions or CVE identifiers have been assigned
Why It Matters
This incident demonstrates the critical vulnerability of package manager build systems to supply chain attacks, where malicious code can be injected through seemingly innocuous dependency resolution rather than direct code execution. For AI practitioners and developers working with Rust-based tooling, this highlights the importance of monitoring build-time dependencies and understanding that compile-time code execution represents a significant attack surface that extends far beyond runtime vulnerabilities.
Technical Details
- The attack used proc-macro1, a typosquat of the legitimate proc-macro2 crate, with identical library source but a malicious build script that reassembled C2 addresses from base64 fragments at build time
- The build script installed a custom certificate verifier that unconditionally accepted all TLS certificates, then deployed platform-specific payloads: Unix/macOS wrote to /tmp/rust-setup and spawned it detached, while Windows used a PowerShell script launched through VBScript to escape Cargo's job object
- The stage-2 implant established persistence through Registry Run keys (Windows), LaunchAgents (macOS), and systemd user services (Linux), supporting commands for termination, C2 reconfiguration, persistence management, and script execution
- Attackers yanked versions 0.3.5-0.3.9 of arrayref simultaneously with publishing the malicious 0.3.10, making it the only non-yanked version and bypassing Cargo's update warnings
- The dependency chain winit → sctk-adwaita → tiny-skia → arrayref demonstrated how transitive dependencies with caret version ranges (^0.3.x) could resolve to the compromised version without explicit developer knowledge
Industry Insight
- Organizations using Rust should implement strict dependency pinning policies and regularly audit build scripts in their dependency trees, particularly for widely-used crates with millions of downloads that serve as critical infrastructure
- Package maintainers should enable two-factor authentication and consider implementing signed releases or attestation mechanisms to detect unauthorized version publishes, as credential compromise remains the primary attack vector
- The Rust ecosystem would benefit from enhanced build script scrutiny mechanisms, such as mandatory build script signing or sandboxed execution environments, to reduce the blast radius of similar supply chain attacks in the future
Disclaimer: The above content is generated by AI and is for reference only.