Skip to main content
Rust Crate Attack: How arrayref Fell in 90 MinutesIncident
4 min readFor Security Engineers

Rust Crate Attack: How arrayref Fell in 90 Minutes

On August 20, 2024, at 01:17 UTC, attackers compromised the maintainer account for arrayref, a Rust crate with over 53 million downloads in the prior 90 days. Within 90 minutes, they published three malicious releases across multiple crates, embedding an infostealer that executed during compilation. Your build process became their deployment vector.

What Happened

Attackers gained control of a legitimate maintainer account and published malicious versions of three crates: arrayref 0.3.10, append-only-vec 0.1.9, and internment 0.8.7. Each release included a typosquatted dependency that executed malicious scripts during the build process, harvesting credentials and system information from developers' machines.

The attack used Rust's build.rs mechanism, which runs arbitrary code at compile time. When developers pulled these versions and ran cargo build, they unknowingly executed the infostealer before their application compiled.

StepSecurity's analysis identified the attack vector: the malicious code posed as legitimate dependency updates, even impersonating trusted maintainer David Tolnay to gain credibility in commit messages.

Timeline

01:17 UTC, August 20: Attackers publish arrayref 0.3.10 with a malicious build script.

01:30 UTC: append-only-vec 0.1.9 released with a similar payload.

01:45 UTC: internment 0.8.7 published, completing the initial wave.

~02:47 UTC: First detection and reporting begin (90-minute window of exposure).

The compressed timeline meant thousands of downloads occurred before the community identified the compromise. Any automated dependency update during this window pulled malicious code.

Which Controls Failed

Maintainer account security: No multi-factor authentication or session monitoring detected the account takeover. The registry had no alerts for unusual publishing patterns from established accounts.

Build-time code execution review: Cargo's build.rs runs with the same privileges as the developer's shell. No sandboxing isolated compilation from the host system.

Dependency verification: The typosquatted dependencies passed through without cryptographic signature verification or namespace protection.

Automated update processes: Teams running automated dependency updates had no pre-deployment scanning to catch malicious build scripts before execution.

Runtime monitoring: Developer workstations lacked endpoint detection to flag unusual network connections or file access during compilation.

What Standards Require

NIST 800-53, Control SA-12 (Supply Chain Protection), mandates that organizations "employ integrity verification tools to detect unauthorized changes to software." This includes verifying the authenticity of software components before integration. The control explicitly requires mechanisms to detect tampering with software and firmware.

ISO/IEC 27001:2022, Control 8.30 (Outsourced Development), requires organizations to supervise and monitor the security of outsourced development activities, including open-source dependencies. You must verify the integrity of code obtained from external sources.

PCI DSS, Requirement 6.3.2, states that custom software is developed securely based on industry standards and incorporates information security throughout the software development lifecycle. This includes validating the security of third-party components before integration into payment processing systems.

SOC 2, CC6.8 (Logical and Physical Access Controls), requires that the entity implements controls to prevent or detect unauthorized access to system components. For development environments, this means controlling what code executes during build processes.

None of these standards say "use open-source carefully." They require specific verification mechanisms that would've caught this attack.

Lessons and Action Items

Implement cryptographic verification for all dependencies. Configure your package manager to require signature verification. For Rust, this means waiting for cargo-crev adoption or implementing your own verification layer. Document which dependencies your team has manually audited versus those you're accepting on trust.

Sandbox your build environment. Run compilation in containers with restricted network access and filesystem permissions. Your build.rs scripts don't need access to ~/.ssh or credential stores. Use gVisor or Firecracker for stronger isolation than standard Docker.

Monitor build-time network activity. Most legitimate builds don't make HTTP requests during compilation. Configure your CI/CD pipeline to alert on any network connections during the build phase. Block outbound connections by default.

Pin exact dependency versions. Your Cargo.lock file should be in version control, and your CI should fail if it changes without explicit approval. Automated updates should stage to a review environment, not production.

Scan dependencies before execution. Tools like cargo-audit check for known vulnerabilities, but you need custom rules to detect suspicious build scripts. Flag any dependency that includes build.rs and executes shell commands or makes network calls.

Implement the two-person rule for dependency updates. One engineer proposes the update, another reviews the diff and the dependency's recent commit history. Look for maintainer changes, unusual commit patterns, or new contributors.

Run dependency updates in isolated test environments first. Your staging environment should use the same dependency versions as production until you've verified new versions don't contain malicious code. This creates a buffer between publication and deployment.

For high-risk environments (payment processing, healthcare, critical infrastructure), vendor your dependencies. Fork the repos you trust, review the code, and control the update cadence. Yes, this creates maintenance overhead. That's the cost of not trusting the public registry.

The arrayref attack succeeded because it exploited the gap between "we use open source" and "we verify what we execute." Your dependency manifest isn't a security control. Verification is.

Topics:Incident

You Might Also Like