On August 20, 2026, three widely used Rust crates were republished from a compromised maintainer account with a single added line in each manifest. That line was a dependency on proc-macro1, a typosquat of the near-universal proc-macro2 crate, whose build script assembled a command-and-control address from base64 fragments and executed a downloaded payload during compilation.

The poisoned releases:

  • arrayref 0.3.10 — live for 86 minutes
  • internment 0.8.7 — live for 90 minutes
  • append-only-vec 0.1.9 — live for 107 minutes

The Rust Security Response Working Group removed all three, along with proc-macro1 and five similar packages, and locked the maintainer’s account.

The Maintainer Was a Victim, Not a Suspect

The account belongs to Andrew Gallant, known in the Rust community as BurntSushi — the author of ripgrep, which carries over 67,000 GitHub stars, and the maintainer of internment and append-only-vec. The Rust security team stated plainly that it does not believe Gallant acted maliciously. His credentials or his machine were compromised.

This is the distinguishing feature of the current generation of registry attacks. There is no malicious package to spot, no unfamiliar author to vet, no suspicious new project to avoid. The package is the one you already trust, published by the person you already trust, under the version number your dependency resolver was already waiting for.

Why the Build Script Matters More Than the Library

The mechanic that makes this attack work is specific to how Cargo handles builds.

proc-macro1’s library source is a genuine copy of proc-macro2. Anything that compiled against it compiled successfully. Tests passed. Binaries ran. Nothing in the resulting artifact looked wrong, because nothing in the resulting artifact was wrong.

The malice lived entirely in build.rs — the build script Cargo executes on the developer’s machine, with the developer’s privileges, before the library is ever linked. The script rebuilt its payload host and C2 address from base64 fragments at build time, fetched the second stage, and ran it.

That means the compromise fired on cargo build. Not on deploy, not at runtime, not in production. On the laptop of every developer and inside every CI runner that resolved a dependency tree containing one of those three versions during the window.

The second stage was a reconnaissance backdoor: credential theft from Chrome, Brave and Edge profiles, system enumeration, and command execution, with persistence via Registry Run keys on Windows, LaunchAgents on macOS and systemd services on Linux.

The Blast Radius Is the Problem

arrayref is not a fashionable dependency. It is a two-hundred-line utility crate that has been quietly correct for a decade, which is precisely why it is everywhere. Wiz’s telemetry puts it in over 35% of all environments it observes — and in roughly three-quarters of all environments where Rust is present at all.

Almost nobody depends on arrayref deliberately. It arrives four levels down a dependency graph nobody has read, and it updates because a lockfile was regenerated or a CI job ran cargo update.

An 86-minute exposure window sounds like a near-miss. Against a crate with that reach, and against CI fleets that rebuild on every push, 86 minutes is a wide net.

The North Korea Overlap

Wiz documented three separate infrastructure links between this campaign and North Korean operations:

  • The arrayref payloads beacon to the path /49890878, the same endpoint used in the Mastra campaign that Microsoft attributed to DPRK / Sapphire Sleet. The hosting IP also shares an SSL issuer with Mastra infrastructure.
  • A compromised organization reported C2 traffic to 23.254.167[.]216, an address that appears in Google Cloud Threat Intelligence’s analysis of UNC1069’s attack on the axios npm package — an actor Mandiant links to North Korea.
  • Both this campaign and the earlier DPRK operations drew from the same 23.254.164.0/23 range at Hostwinds LLC.

Infrastructure reuse is suggestive rather than conclusive, and shared hosting ranges are the weakest link in the chain. But the endpoint collision and the SSL issuer match are harder to explain as coincidence, and the tradecraft fits: DPRK crews have spent two years converting developer trust into initial access, from Shai-Hulud’s npm worm onward. Developer machines hold source access, cloud credentials and signing keys. For an operation funded by theft, that is a better target than the production estate.

What To Do Now

Check whether you pulled a poisoned version. The bad releases can persist in your local Cargo cache even after being yanked from crates.io. Search ~/.cargo/registry for arrayref-0.3.10, internment-0.8.7, append-only-vec-0.1.9 and any proc-macro1 artifact. The Rust Project’s advisory publishes a verification command.

Treat a hit as a compromised host, not a bad dependency. The payload ran with your user’s privileges and stole browser credentials. Cleaning the cache does not undo that. Rotate every credential reachable from the affected machine or runner — cloud keys, registry tokens, SSH keys, signing material — and rebuild CI runners rather than patching them.

Audit build scripts as executable code, because they are. Most dependency review focuses on what a library does at runtime. build.rs, postinstall, and their equivalents in every other ecosystem run first, unsandboxed, on the machine with the most privilege in the pipeline.

Stop letting CI resolve floating versions. Commit lockfiles, pin transitive dependencies, and delay adoption of new releases. A build that would have picked up arrayref 0.3.10 on August 20 and one that would have picked it up on August 21 are separated only by policy.

Sources