A supply chain attack against the Rust ecosystem has compromised two crates with a combined download history in the hundreds of millions, turning a routine software build into a malware installation event for any developer who compiled a project depending on them.
Researchers at Aikido Security uncovered the campaign after spotting a newly published package quietly reaching out to a remote server and executing a downloaded file during its build process, behavior that has no legitimate reason to exist in a Rust build script.
A Typosquat That Became a Trusted Dependency
The malicious package was named proc-macro1, a near-perfect typosquat of proc-macro2, one of the most widely relied-upon crates in the entire Rust ecosystem. Its author copied the legitimate crate’s description and documentation almost exactly, making it look like a normal, trustworthy library to anyone browsing the registry.
On its own, a typosquat with a handful of downloads would be a minor nuisance easily missed in the noise. What turned this into a serious incident was what happened next: within the same hour that proc-macro1 appeared, two established and popular crates, arrayref and append-only-vec, both maintained by the same developer, suddenly added the fake package as a dependency. Together those two crates account for hundreds of millions of historical downloads, instantly giving the malicious code an enormous potential reach.
Hidden Where Code Review Would Never Look
What makes this compromise particularly effective is where the malicious logic was placed. The visible, human-readable source code of arrayref and append-only-vec was never touched and remained completely legitimate. A manual code review of either crate would have found nothing wrong.
The actual attack was buried in a single injected dependency line in each crate’s manifest file, pointing to a specific version of proc-macro1. That crate’s build.rs script, a file that Cargo automatically compiles and executes during every single build with no developer action required, contained the malicious payload delivery logic. Developers never had to call a function or explicitly reference the compromised crates to get infected; simply building a project that depended on them was enough.
Cross-Platform Infostealer With Persistence
Once triggered, the build script downloaded a platform-specific binary tailored to Linux, Windows, or macOS from a remote server referenced only by a bare IP address, with the destination obfuscated using base64-encoded fragments specifically designed to slip past string-based malware scanners.
On Unix-based systems, the payload was written to disk, flagged executable, and launched as a detached background process so it would keep running independently even after the build completed. Analysis of the recovered binaries showed the malware functions as a fully capable infostealer, with the ability to:
- Harvest saved credentials from Chromium-based browsers, including Chrome, Brave, and Edge.
- Extract data from browser extension storage, a location frequently used to store cryptocurrency wallet keys and session data.
- Establish persistence on macOS through a LaunchAgent configured to automatically relaunch the malware at every user login.
- Maintain an active connection to a command-and-control server capable of issuing remote shell commands to the infected machine.
The stealth of the entire operation came from abusing standard, expected package build automation rather than modifying any application logic a developer or automated tool would think to inspect.
Why Build Scripts Are a Growing Blind Spot
This incident is part of a broader pattern of attackers targeting developer tooling and build configurations rather than application code itself. Because build scripts execute automatically and often with the same privileges as the developer running them, they represent a uniquely trusted execution path that many security review processes simply do not scrutinize the way they scrutinize application logic.
For an ecosystem like Rust’s crates.io, where dependency chains can pull in dozens or hundreds of transitive packages, a single compromised maintainer account or a well-disguised typosquat can ripple outward with alarming speed, exactly as this incident demonstrated within the span of a single hour.
What Developers and Organizations Should Do
- Audit dependency trees for any project that references
arrayref,append-only-vec, orproc-macro1, and remove or pin to known-clean versions immediately. - Treat any machine that built a project pulling in the compromised crates as potentially infected, and run credential and browser-data compromise checks accordingly.
- Rotate credentials, especially browser-saved passwords and cryptocurrency wallet secrets, on any potentially affected development machine.
- Consider build isolation, such as containerized or sandboxed build environments, to limit what a malicious build script can reach on the host system.
- Monitor for outbound network connections to unfamiliar IP addresses during routine build and CI/CD processes, which can be an early warning sign of exactly this kind of attack.
The Rust ecosystem has generally enjoyed a reputation for strong tooling and safety guarantees at the language level, but this incident is a reminder that memory safety says nothing about supply chain integrity. As long as build automation runs untrusted code with developer-level privileges, attackers will keep looking for exactly this kind of opening.
Leave a Reply
You must be logged in to post a comment.