Skip to main content
Rust Crate Attack: What 86 Minutes Taught Us About Supply Chain DefenseIncident Management
5 min readFor External Auditors and Assessors

Rust Crate Attack: What 86 Minutes Taught Us About Supply Chain Defense

The Challenge

In early 2025, the Rust Security Response Team received a tip about a suspicious crate called proc-macro1. This led to the discovery of a sophisticated supply chain attack that turned a popular Rust package into malware distribution infrastructure.

The attacker compromised the credentials of a legitimate package maintainer and published malicious versions of three widely-used crates: arrayref (245 million lifetime downloads), internment, and append-only-vec (over 4 million downloads). The malicious code added a single dependency, proc-macro1, a typosquat of the legitimate proc-macro2 package, whose build script downloaded and executed platform-specific infostealer malware targeting browser credentials and cryptocurrency wallets.

The poisoned releases were live on crates.io for 86 to 107 minutes before removal. During that window, any developer running cargo build on a project that depended on these packages would execute the malicious build script, potentially compromising their development environment.

The Environment and Constraints

The attack exploited three structural characteristics of modern dependency management that make detection difficult:

  • Automatic build script execution. Cargo runs build.rs files during compilation without additional confirmation. This design prioritizes developer convenience but creates an execution vector that doesn't require explicit user action beyond running a build command.

  • Opaque transitive dependencies. Most developers don't audit every package in their dependency tree. When arrayref added proc-macro1 as a dependency, projects that depended on arrayref inherited that dependency automatically. The malicious code never appeared in the direct dependencies developers typically review.

  • Urgency from package yanking. The attacker yanked recent legitimate releases of arrayref, making the poisoned version the default choice for developers updating dependencies. This tactic weaponized the package manager's version resolution logic.

The Rust Security Response Team faced typical constraints: confirming malicious behavior, identifying all affected packages, removing them from distribution, and notifying the community, all while the attack was potentially ongoing and the maintainer's account remained compromised.

The Approach Taken

Nextron Systems' research team initially identified proc-macro1 and reported it to the Rust Security Response Team. The investigation revealed the build.rs file contained code that:

  1. Identified the target system's operating system and processor architecture.
  2. Downloaded a matching second-stage payload from a remote server.
  3. Executed the payload with capabilities to steal Chromium-based browser data, target cryptocurrency wallet extensions, establish persistence, and receive commands from the attacker's infrastructure.

The response team locked the compromised maintainer's account and removed the malicious releases. Arrayref 0.3.10 was available for 86 minutes, internment 0.8.7 for 90 minutes, and append-only-vec 0.1.9 for 107 minutes before deletion. They also removed five additional suspicious crates: proc-macro-en, aovine, arone, aronenao, and tinymember, treating every version as malicious.

The team issued a public disclosure advising developers to check Cargo lockfiles and local registry caches for the affected packages.

Results and Metrics

The Rust team removed the malicious packages within two hours of detection. However, the disclosure did not include:

  • How many developers downloaded the poisoned releases during the exposure window.
  • How many build environments executed the malicious build scripts.
  • Whether the second-stage payload successfully exfiltrated credentials or established persistence on any systems.
  • The method used to compromise the legitimate maintainer's credentials.

This information gap is typical of supply chain attacks where registry operators can control distribution but have limited visibility into downstream execution and impact.

What They Would Do Differently

The Rust Security Response Team has not published a retrospective, but the attack surface suggests several detection and prevention opportunities:

  • Build script sandboxing. Cargo could restrict build script network access by default, requiring explicit capability grants for scripts that need to download resources. This would make proc-macro1's remote payload fetch immediately suspicious.

  • Dependency diff alerts. Registry operators could flag when a new release adds dependencies that weren't present in previous versions, especially dependencies with similar names to established packages (proc-macro1 vs. proc-macro2). This pattern should trigger manual review before publication.

  • Maintainer account monitoring. Unusual publishing patterns, multiple packages updated simultaneously, legitimate versions yanked, new dependencies added, could trigger two-factor authentication challenges or delay publication for manual review.

Takeaways for Your Team

If you're assessing an organization's secure development lifecycle under SOC 2 or ISO/IEC 27001 Annex A 8.31 (Security requirements for development and acquisition), this attack reveals specific control weaknesses to evaluate:

  • Dependency pinning isn't sufficient. Organizations that pin exact versions in lockfiles avoided this attack only if they hadn't updated dependencies during the exposure window. Pinning prevents unexpected updates but doesn't prevent malicious code in the pinned version.

  • Build environment isolation matters. Development machines that execute builds should not have access to production credentials, API keys, or sensitive data stores. The infostealer targeted browser profiles and cryptocurrency wallets, but the same execution vector could access SSH keys, cloud provider credentials, or source code repository tokens stored on the developer's machine.

  • Registry monitoring is detective, not preventive. Your audit evidence should show how your organization detects compromised dependencies, not just how you select them. This means monitoring security advisories, running dependency scanning tools that check against known malicious packages, and maintaining an incident response process for supply chain compromises.

  • Transitive dependency review is impractical without tooling. Manual code review of direct dependencies is feasible. Reviewing every transitive dependency in a modern application is not. Your controls should acknowledge this limitation and compensate with automated scanning, build environment restrictions, and network egress monitoring that detects unexpected outbound connections during builds.

The attacker's choice of arrayref was strategic: a package with 245 million downloads provides enormous reach, and its legitimate functionality meant the poisoned version would pass superficial testing. Your assessors should ask not whether your developers review dependencies, but whether your Technological Controls would detect or contain a compromised package that behaves normally except for a single malicious build script.

The 86-minute exposure window demonstrates that supply chain attacks operate on timescales where human review can't keep pace. Your controls need to assume compromise and limit the blast radius when it occurs.

You Might Also Like