Light bulb Limited Spots Available: Secure Your Lifetime Subscription on Gumroad!

Aug 20, 2026 · 7 min read

Poisoned Rust Crate Ran Infostealer at Compile Time

At 07:15 UTC on 20 August 2026, version 0.3.10 of arrayref went live on crates.io from a compromised maintainer account. It survived 86 minutes. Nobody had to call a function from the crate to be hit, because the malware ran while the project was still compiling.

Most dependency malware waits. It sits in an imported module until your code reaches it, which gives review and static analysis a chance to catch it. This one did not wait. The payload lived in a build script, and a build script runs before your program exists.

Key Takeaways

  • arrayref 0.3.10 went live on crates.io at 07:15 UTC on 20 August 2026 and was pulled 86 minutes later, from a crate with 245 million lifetime downloads.
  • proc-macro1 1.0.107, a typosquat of David Tolnay's proc-macro2, carried a build.rs script that reassembled the address 23.254.165.112 from base64 fragments and pulled an OS specific second stage over TLS with certificate validation disabled.
  • internment 0.8.7 and append-only-vec 0.1.9 carried the same dependency from the same hijacked account, user 2402, registered in 2009 to maintainer David Roundy.
  • Wiz found the stage two implant reading Chrome, Brave and Edge login databases through SQLite queries and persisting through a Windows Registry Run key, a macOS LaunchAgent or a Linux systemd user service.
  • RUSTSEC-2026-0260 lists no patched version, so the fix is pinning: arrayref =0.3.9, internment =0.8.6, append-only-vec =0.1.8.

What Happened to arrayref on 20 August 2026?

An attacker took over the crates.io account behind arrayref and published a release whose only real change was a new dependency. The advisory issued the same day, RUSTSEC-2026-0260, describes it plainly: a new version of arrayref was published with a direct dependency on proc-macro1, which would execute a malicious build script.

The choreography was tight. A GitHub account impersonating David Tolnay was created at 01:17 UTC. A benign proc-macro1 1.0.106 went up at 01:55 to make the crate look lived in. The weaponised 1.0.107 followed at 07:11, and arrayref 0.3.10 four minutes later. Reported at 07:54, proc-macro1 was gone by 08:03 and arrayref by 08:41, as BleepingComputer documented.

arrayref is not a package anyone chooses. It arrives underneath blake3, underneath the egui, eframe and iced GUI stacks, underneath Ethereum and Solana tooling. At its average rate of 53 million downloads per 90 days, roughly six requests a second, an 86 minute window covers something near 35,000 download events. No confirmed use of the malicious version has surfaced, which is luck rather than architecture.

Why Does cargo build Run Attacker Code Before Any Test Does?

Because Cargo compiles and executes the build script of every dependency in your graph as an ordinary native binary, with your user's privileges, before it compiles your crate. The Cargo book's build script reference is explicit that build.rs exists to do arbitrary work. Arbitrary is the operative word: no sandbox, no capability declaration, no network policy.

Reviewing a dependency public API therefore tells you nothing about what happens at compile time, and a container does not help when it holds your SSH agent socket and your cloud tokens, which on most CI runners it does. The Rust project has an open goal to explore sandboxed build scripts, and the honest caveat inside that work is that sandboxing cargo build helps less than it sounds when everyone runs cargo test seconds later.

Ecosystem comparisons are worth making carefully here. npm's postinstall hook has the same shape and we have covered it repeatedly, including North Korea poisoning 141 npm packages through Mastra AI and the Miasma worm hitting 32 Red Hat npm packages. The difference is cultural. npm shops have spent years learning to run installs with scripts disabled, while Rust has no equivalent switch in common use, because build.rs is how a large slice of the ecosystem links to C libraries at all.

How Did the Attacker Steer Developers Onto the Bad Version?

By yanking the good ones. Immediately after publishing 0.3.10, the hijacked account yanked arrayref 0.3.5 through 0.3.9, and cargo yank exists precisely to tell people a release is bad. Cargo starts printing a warning suggesting you update to a version that is not yanked. The only version that was not yanked was the poisoned one.

That is the detail worth taking from this incident. The attacker turned a safety mechanism into a funnel. A yank warning used to read as maintenance noise; after 20 August it reads as a prompt to check who published what.

A small wooden shipping crate on a developer's desk beside an open laptop with a softly glowing screen in a dim home office at dusk

What Did the Second Stage Actually Steal?

Browser credentials, host information and a foothold. Analysis reported by The Hacker News describes the implant querying the SQLite login databases used by Chrome, Brave and Edge, then installing itself for restart through a Registry Run key on Windows, a LaunchAgent on macOS or a systemd user service on Linux.

The dropper was unsubtle in a way that helps defenders. It wrote /tmp/rust-setup on Unix hosts, and rust-setup.ps1 plus rust-setup-launch.vbs into the Windows temp directory, launching the latter through wscript.exe so the process outlived the Cargo job object that spawned it. Traffic went to 23.254.165.112 on ports 9089 and 443.

Wiz noted meaningful infrastructure overlap with recent North Korean supply chain operations, naming the Mastra campaign and the compromise of the axios npm package. No vendor has formally attributed this incident to a named group, and that distinction matters: overlapping hosting is a lead, not a verdict.

What Browser Credential Theft Means for Your Email Accounts

A stealer that reads Chrome, Brave and Edge login databases is aiming at your mailbox first. The saved credential list on a developer machine nearly always holds a personal Gmail or Outlook login and the work identity provider behind it, and email unlocks the rest, because password resets for GitHub, npm, crates.io and AWS all land there.

The chain runs further than most incident notes suggest. Whoever holds your mailbox can approve a reset for your registry account, and a registry account is what turns one infected laptop into the next arrayref. Developer credentials are not the prize here, they are the delivery mechanism for the next batch of victims, and the account hijacked in this case had been publishing crates since 2009.

Worry hardest about session cookies, since a stolen session bypasses the password and often the second factor with it. If you built anything on a machine that touched these versions, treat the mailbox as compromised until you have signed out of every session, checked forwarding rules and app passwords, and reviewed your Google account security activity.

What Should You Check Right Now?

Start with lockfiles, then caches, then egress logs. Grep every Cargo.lock in your repositories for arrayref 0.3.10, internment 0.8.7, append-only-vec 0.1.9 and any mention of proc-macro1, and search ~/.cargo/registry/cache for the matching .crate files, since deleted versions leave no trail through cargo audit once they are pulled from the index. Then pin the safe versions with exact requirements.

On the host side, look for /tmp/rust-setup, rust-setup.ps1 and rust-setup-launch.vbs, an unexpected systemd user service, a new LaunchAgent, or an unfamiliar Run key. Check CI logs from the 07:11 to 09:25 UTC window on 20 August for any job that resolved fresh dependencies rather than building with a committed lockfile. An ephemeral runner being destroyed after the job does not clear it, because exfiltration happened during the build.

If anything matches, rotate broadly rather than surgically: SSH keys, cloud tokens, CI secrets, signing keys and crates.io API tokens, and rebuild any artefact produced in that window on clean infrastructure.

Does the crates.io Trust Model Need to Change?

The registry response was fast, six minutes from report to removing proc-macro1, and that speed is still the wrong thing to rely on. Two structural fixes already exist and are underused. Trusted publishing replaces the long lived API token, the likely root of this compromise, with short lived OIDC credentials scoped to one CI workflow. Building with --locked removes the surprise resolution that made a brand new version reachable at all.

The third fix is duller and probably more effective: a cooldown that refuses any crate version younger than a few days. Every timeline for this incident is measured in minutes, so a 48 hour delay would have made the campaign a non event. Nobody needs a dependency that shipped 90 minutes ago.

Long lived API tokens are the recurring weak point across all of this. Truffle Security's audit of four years of public data found 9,300 leaked AWS keys of which 88 percent still worked, with a median exposure of five years — the same credential lifecycle failure, measured at scale.

Stop Email Tracking in Gmail

Spy pixels track when you open emails, where you are, and what device you use. Gblock blocks them automatically.

Try Gblock Free for 30 Days

No credit card required. Works with Chrome, Edge, Brave, and Arc.