Home/ Blog/ Security news/ Article
Blog · Security news

Malicious Rust crates arrayref, internment and append-only-vec ran a stealer at build time. Pin now.

Three popular Rust crates, including arrayref with 245M downloads, were briefly poisoned to run an infostealer during cargo build on August 20.

Robotic arm setting a cracked block into a larger machined structure

The crew that spent this year poisoning JavaScript packages just added a second language. On August 20, someone using a compromised maintainer's crates.io account pushed booby-trapped releases of three popular Rust libraries, one of them downloaded 245 million times, wired to run a credential stealer the moment a project compiled. The Rust Security Response Team pulled all three within about two hours. That speed is the reassuring headline and also the misleading one, because two hours is a long time when the payload fires on cargo build.

The value of this story is not the individual bug. It is what the incident tells you about who is running these operations now, and about the one control that would have blunted it.

What landed on crates.io

The poisoned releases did not carry the malware directly. Each one added a dependency on proc-macro1, a typosquat of proc-macro2, a genuine crate that almost every Rust project pulls in transitively. The malicious code lived in that typosquat's build script, the build.rs file that Cargo runs at compile time. The Hacker News described the sequence: the script stitches a remote address back together from base64 pieces, stands up a TLS verifier rigged to approve every certificate so nothing flags the connection, then pulls down a follow-on binary and runs it. It fired on cargo build, cargo check, and cargo test, so even opening the project in an editor that quietly runs a check in the background was enough to set it off.

The second stage is a full backdoor, and it sets up housekeeping on whatever operating system it lands on. Wiz found it planting a startup entry to survive reboots: a Run key in the Windows registry, a login agent on macOS, a per-user background service on Linux. Its first job is theft, reaching into the saved-password stores of Chrome, Brave, and Edge and reading the logins out of their local databases. The dropper stays quiet about how it lands, staging an executable at /tmp/rust-setup on Unix hosts and, on Windows, hiding a PowerShell script behind a VBScript launcher in the temp folder.

CrateMalicious versionTime onlineSafe pin
arrayref (245M downloads)0.3.10~86 minutes0.3.9 or earlier
internment0.8.7~90 minutes0.8.6 or earlier
append-only-vec0.1.9~107 minutes0.1.8 or earlier
Source: Rust Security Response Team advisory, August 20, 2026.

The Rust team's read is that the arrayref maintainer was not a willing participant, and that either their machine or their publishing credentials had been taken over. How that happened has not been disclosed. The lower versions of arrayref were yanked under the same account, which turns Cargo's own helpfulness into the lure: the tooling nudges you to move off a yanked version, and the only non-yanked release on offer was the poisoned one. An update prompt from a package manager is not a safety signal, and this incident is a clean demonstration of why.

This is npm's attacker, wearing a new coat

The most useful read here is not "Rust had a bad day." It is that the same operation behind two earlier package-registry compromises has ported a proven playbook to a new language. Wiz traced the crates.io infrastructure to the same rented address range at Hostwinds, a shared TLS certificate issuer, and a reused callback path that appeared in the Mastra npm compromise that Microsoft attributed to a North Korean group, and in the axios attack that Google linked to the same country. The build-time execution, the fake TLS verifier, and the browser-credential theft are the same moves we documented in those npm cases.

Attribution deserves an honest caveat. No vendor has formally pinned the crates.io incident on a named actor, and the links Wiz drew are infrastructure overlaps, not a confession. But the pattern is consistent enough that treating this as an isolated Rust event misses the point. A professional supply-chain team does not care what language you write in. It cares that your build runs untrusted code from a registry you implicitly trust, and that is true of Cargo, npm, and PyPI alike. If you have watched these registry compromises stack up, the trajectory is toward more languages, not fewer.

Two hours offline is not a control

Fast takedown reads like a win, and the response here was genuinely quick. It is also the wrong metric to feel good about. Deletion stops new downloads; it does nothing for the builds that already ran. Any continuous-integration job that resolved arrayref 0.3.10 in its 86-minute window compiled the payload and is compromised, deletion or not. Worse, a lockfile that captured the bad version propagates it to every teammate and every downstream build until someone notices, long after the crate is gone from the registry.

There is a control that changes this math, and Rust does not have it yet. A mandatory publish-age delay holds brand-new package versions out of default resolution for a set period, so a malicious release that lives for two hours never reaches a build in the first place. npm and PyPI both offer cooldown mechanisms of this kind. Cargo's equivalent, an open proposal called global-min-publish-age, was still unmerged as of August 21. We flagged this exact gap when we looked at release cooldowns across registries, and this incident is the argument for it written in real time. A cooldown would have made the whole attack a non-event.

Assume the window, then hunt

Pinning closes the door going forward. Hold arrayref at a build no later than 0.3.9, internment at 0.8.6, and append-only-vec at 0.1.8, then confirm your lockfile does not reference any of the malicious releases. That is the easy half.

The half that matters is retrospective: did any build host resolve a poisoned version on August 20 before it was pulled? Search ~/.cargo/registry/cache for the deleted versions, and check CI logs for builds that ran in the windows above. On any host that did, treat it as a credential-theft incident, not a dependency bump. Rotate anything stored in Chrome, Brave, or Edge, check for the persistence artifacts (a new Registry Run key, a macOS LaunchAgent, or a systemd user service), and hunt the known C2 addresses in your egress logs along with any rust-setup files in temp directories. The same post-compromise cleanup applies whether the poisoned package was Rust or JavaScript.

This is also where detection strategy earns its keep. A file-integrity scan of your source tree finds nothing, because the malicious code never touched your repository. What you want is telemetry on process behavior: a compiler toolchain that spawns a network client and writes an executable to a temp path is the signal, and a new user-level persistence unit appearing right after a build is the confirmation. Managed detection that watches process lineage and persistence changes, rather than just scanning files, is what catches a build-time compromise while it is happening.

Topics

Frequently asked questions

Which Rust crates were compromised on August 20, 2026?

Malicious versions of arrayref (0.3.10), internment (0.8.7), and append-only-vec (0.1.9) were published to crates.io and removed within about two hours. Each added a typosquatted dependency, proc-macro1, whose build script ran an infostealer during compilation.

How did the malicious Rust crates run code during a build?

The poisoned crates depended on proc-macro1, a typosquat of proc-macro2. Its build.rs script ran at compile time, disabled TLS certificate validation, downloaded a second-stage binary, and executed it during cargo build, check, or test. No manual step was required.

Am I affected if my project uses arrayref?

You are at risk only if a build host resolved arrayref 0.3.10, internment 0.8.7, or append-only-vec 0.1.9 during the roughly two-hour window on August 20, 2026. Check your Cargo cache and CI logs, and pin arrayref to 0.3.9 or earlier.

Who was behind the Rust crates supply chain attack?

No vendor formally attributed the crates.io incident to a named group. Wiz reported infrastructure overlaps with the earlier Mastra and axios npm compromises, which Microsoft and Google linked to North Korean actors. The attribution here is circumstantial, based on shared infrastructure.

What should I do if a build pulled the poisoned versions?

Treat that host as compromised. Rotate credentials stored in Chrome, Brave, and Edge, check for persistence such as a Registry Run key, a macOS LaunchAgent, or a systemd user service, hunt the known command-and-control addresses in egress logs, and remove any rust-setup files from temp directories.

Would a version cooldown have stopped this attack?

Likely yes. A mandatory publish-age delay keeps brand-new package versions out of default resolution for a set period, long enough to catch a two-hour malicious release. npm and PyPI offer cooldown controls; Cargo's global-min-publish-age proposal was still unmerged as of August 21, 2026.

See what Suriq finds on your own servers.

Agentless checks for uptime and your cloud, a lightweight agent for detection on each server, and one console that ranks and explains what it finds.