Build1 publisher3 min readPublished
Cargo's own yank warning steered builds to the poisoned arrayref 0.3.10
Malicious arrayref 0.3.10 was downloaded 2,285 times from crates.io in the 86 minutes before Rust's security response team deleted it on August 20. Lockfiles still pinned to 0.3.9 kept most builds away from its unsandboxed build-script payload.
The Engineer · Build desk
Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

What happened
- The payload sat in proc-macro1, a proc-macro2 look-alike added as arrayref's one new dependency, whose build script downloaded and started a binary during compilation.
- proc-macro1 was published by an account named dtolney, one letter off dtolnay, the handle of David Tolnay, who maintains the real proc-macro2.
- The attacker yanked arrayref 0.3.5 through 0.3.9, leaving the poisoned 0.3.10 as the only release that was not yanked.
- Two more crates on the same account, internment and append-only-vec, were hit the same way, and the Rust blog treats their author as a likely compromised victim.
- Six attacker crates were deleted in all, among them proc-macro1, proc-macro-en and tinymember.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- exposure Any of arrayref's 400 reverse dependencies could run proc-macro1's build script without naming it, so a security scan limited to direct dependencies would have reported nothing.
- decision Upgrading because Cargo reports a yanked version now means trusting whoever controls the maintainer's account, and the person who filed the RustSec issue was caught exactly that way.
- constraint Because Cargo offers no sandbox for build scripts or proc macros, any isolation of CI runners and laptops has to be built and maintained around Cargo by each team.
Before Cargo compiles a crate, it compiles that crate's build.rs and runs it on the developer's machine, with the developer's permissions [14]. Proc macros run the same way inside rustc [16]. There is no sandbox [14]. Build scripts exist to find and compile C libraries, generate bindings and embed version info, and the arrayref payload used the feature as designed [15][1].
Delivery took one manifest line. SafeDep's diff shows arrayref 0.3.10 gained exactly one entry, the proc-macro1 dependency, and nothing in arrayref's source uses it [17]. "Cargo builds every declared non-optional dependency, whether or not the code uses it," SafeDep wrote [18]. The requirement, `version = "1.0.107"`, is a caret requirement. Only 1.0.106 and 1.0.107 existed, so it resolved to the malicious release [19]. A project that depended on arrayref got proc-macro1's build script without its own manifest ever mentioning proc-macro1 [17][18].
The rest of proc-macro1 was made to look legitimate. Its src/ was a genuine copy of proc-macro2, the crate almost every Rust macro depends on, down to copied issue references [6][23]. Code that used it compiled and worked [6]. Per SafeDep, the manifest forged David Tolnay as author and linked a repository under dtolnay that returns 404 [21]. The change a reviewer could have seen was in the build section: version 1.0.107 added base64, rustls and ureq as build dependencies [22].
The yank is the part I'd study first. A yanked version stays downloadable for existing lockfiles, but Cargo warns about it and suggests "consider updating to a version that is not yanked" [8]. With 0.3.5 through 0.3.9 yanked, that suggestion had one destination [7]. jhobern, who filed the RustSec issue, wrote that the warning "is the lure. That is how I hit it." [20] A yank is normally a maintainer flagging a bad version. The author of the dev.to write-up described this one plainly: "Here it was an attacker telling you to install theirs." [24]
Most builds were protected by a file teams already commit. Per RUSTSEC-2026-0260, the 2,285 downloads of 0.3.10 were under 10% of arrayref's traffic in the window, because most lockfiles still held 0.3.9 [4]. That puts arrayref's total downloads during those 86 minutes above 22,850 [1][2]. The takedown was good work: published at 07:15 UTC, gone at 08:41 [3]. The dev.to author still rates the response "NEEDS REVIEW", because after the deletion the crate page, cargo audit and the build-script model tell users almost nothing [10].
I'd order the defences by where this attack worked:
1. A committed lockfile. It kept most builds on 0.3.9 [4]. 2. Review of changes to the resolved dependency set. proc-macro1 entered the graph without appearing in any downstream manifest, and it brought three new build dependencies with it [17][22]. 3. Build isolation from the network and from credentials. Cargo provides none, and this payload had to download its binary at build time [14][1].
What to watch
- Any RustSec or Rust blog account of what the downloaded binary did once started; teams that built between 07:15 and 08:41 UTC need it to know what to rotate.
- Whether Cargo changes its yank warning when every older release of a crate is yanked from one account in a short span, the pattern this attack relied on.
- Download counts for the poisoned internment and append-only-vec releases, to see whether lockfiles protected their users as well as they protected arrayref's.