Rust crates `arrayref` 0.3.10 + `internment` 0.8.7 + `append-only-vec` 0.1.9 poisoned with a build-time dropper via typosquat dependency `proc-macro1` (crates.io, 2026-08-20, 245M+ combined downloads, DPRK-overlap attribution)
Compromised maintainer accounts published arrayref@0.3.10 (244M downloads), internment@0.8.7, and append-only-vec@0.1.9 to crates.io. Each release added a single dependency line on typosquat crate proc-macro1, whose build.rs downloads and executes a platform-specific payload from 23.254.165.112:9089 during cargo build. Wiz attributes overlap to DPRK campaigns.
- Threat actor
- DPRK-linked (Wiz-reported infrastructure overlap with Famous Chollima / Contagious Interview campaigns)
- Detected by
- Socket · Wiz · SafeDep · Semgrep · StepSecurity · Aikido Security · Rust Security Response Team
- Also known as
- arrayref supply chain attack · proc-macro1 build-time dropper · 2026-08-20 crates.io compromise · Rust arrayref internment append-only-vec attack
- Ecosystems
- crates.io
- Packages tracked
- 5
What happened
On the morning of 2026-08-20 UTC, a coordinated build-time supply-chain attack landed on crates.io. Between 07:11 and 09:25 UTC, three widely-used Rust crates were republished with a single-line manifest change that pulled in a typosquat dependency called proc-macro1; whenever any host on the internet subsequently ran cargo build, cargo update, or a CI resolve step that touched those crates, the compromised build.rs fired and dropped a target-matched infostealer binary. All three crates and the dropper were yanked by the Rust Security Response Team within 3 hours, but the reach is unusually large because arrayref is a foundational transitive dependency across most of the Rust ecosystem (Wiz observed it in ~75% of environments where any Rust is present).
Affected crates and takedown windows
| Crate | Malicious version | Publisher account | Published (UTC) | Yanked (UTC) | Downloads | |---|---|---|---|---|---| | arrayref | 0.3.10 | droundy (compromised) | 2026-08-20 07:15 | 08:41 | 244M all-time, 53.7M in 90 days | | internment | 0.8.7 | (compromised maintainer) | 2026-08-20 07:34 | 09:04 | 14M all-time | | append-only-vec | 0.1.9 | (compromised maintainer) | 2026-08-20 07:37 | 09:25 | 4M all-time | | proc-macro1 (dropper) | 1.0.107 | dtolney (compromised) | 2026-08-20 07:11 | 08:03 | new crate, typosquat of proc-macro2 | | proc-macro-en (dropper variant) | seen | - | 2026-08-20 window | - | new crate |
Each compromised release added a single dependency line to Cargo.toml naming proc-macro1. The library source of proc-macro1 is a genuine copy of proc-macro2, so builds succeed with no compile-time signal - all malice sits inside build.rs. To create update pressure toward the poisoned arrayref@0.3.10, the attacker also yanked all prior versions 0.3.5 through 0.3.9, so any cargo resolver rolling a ^0.3 range forward landed on the malicious release; the Rust Security Response Team subsequently un-yanked the clean prior versions after the incident.
Payload behaviour (build.rs)
The malicious build.rs runs during compilation, before any code the developer wrote executes. It:
- Reconstructs C2 URLs from base64-encoded fragments so a static scan for the literal IP string misses it.
- Constructs a
rustlsclient with a customAcceptAllverifier (TLS verification disabled) so a self-signed C2 cert works. - Downloads a target-specific binary from
23.254.165.112:9089under one of four names (rust-crate_0.1.0,_0.2.0,_0.3.0,_0.4.0) matched to Linux x86-64, Windows x86-64, macOS x86-64, macOS ARM64. - Passes the second C2 endpoint
23.254.165.112:443asargv[1]to the executed binary for follow-up traffic.
On Unix, the payload lands at /tmp/rust-setup and is spawn-detached from cargo. On Windows the dropper writes %TEMP%\rust-setup.ps1 and a VBScript launcher rust-setup-launch.vbs, then launches via wscript.exe with CREATE_NO_WINDOW; the dropper also calls std::mem::forget() on the child process handle so the payload survives after cargo build completes - the child escapes the build job object and keeps running.
Blast radius
arrayref is a small primitive crate (fixed-length array reference helpers) that ended up as a foundational transitive dependency in most of the Rust ecosystem. Direct dependents include blake3 (widely-used hash), Rust GUI frameworks (egui, eframe, iced), and Rust plumbing under winit / sctk-adwaita / tiny-skia used by nearly every native Rust GUI app. Wiz observed arrayref present in ~35% of all environments they scanned, and ~75% of environments where any Rust is present - so an org that builds ANY modern Rust code (a Solana or Ethereum tool, a Tauri or Iced desktop app, a Rust-backed CLI) has a high probability of pulling arrayref transitively without ever writing a direct [dependencies] entry.
Any host that ran cargo build, cargo update, cargo check, cargo test, or CI resolution touching these crates between 07:11 and 09:25 UTC on 2026-08-20 executed the payload. This includes shared CI runners on GitHub Actions, GitLab CI, Buildkite, and self-hosted CI - a runner that resolved once and then rebuilt with cache would have executed the payload on the first build and then persistently held whatever backdoor artifacts the payload dropped.
Attribution
Wiz reported significant overlap with DPRK / Lazarus supply-chain infrastructure - naming conventions and payload behaviour align with prior Famous Chollima / Contagious Interview activity that has been running against ecosystem maintainers for over a year. Both publishing accounts (droundy and dtolney) appear compromised via credential theft, not sock puppets. droundy is the long-standing maintainer of arrayref since 2015; the Rust Security Response Team locked both accounts as a precaution.
Detectability
A passive scanner that only hashes arrayref's own source misses this attack entirely - the arrayref source is unchanged. Detection requires either (a) resolving the full dependency graph and flagging previously-unseen crate names, (b) monitoring build.rs execution for outbound HTTP to fresh IPs, or (c) hashing Cargo.toml for the specific version window and alerting on the added proc-macro1 line. This attack shape will recur; teams that rely purely on source-code hashing for supply-chain defence will keep missing it.
Discovery credits and timeline
Socket AI Scanner (independent detection at 07:29:50 UTC, ~15 minutes after arrayref was published), Wiz Threat Research (DPRK attribution), SafeDep, Semgrep, StepSecurity, Aikido Security. RUSTSEC advisories filed via rustsec/advisory-db#3161. Rust Security Response Team (crates.io) took down the malicious releases and locked publishing accounts.
Affected packages (5)
- crates.ioappend-only-vec0.1.9
- crates.ioarrayref0.3.10
- crates.iointernment0.8.7
- crates.ioproc-macro-en
- crates.ioproc-macro11.0.107
These are usually pulled in as transitive dependencies rather than installed directly. Check your whole tree at once - it runs in your browser and nothing is uploaded.
Impact
- Affected crates and windows on crates.io (2026-08-20):
arrayref@0.3.10published 07:15 UTC by compromised accountdroundy, live 86 minutes, yanked 08:41 UTC (244M all-time downloads, 53.7M in last 90 days, 403 direct dependents);internment@0.8.7live ~90 minutes, yanked 09:04 UTC (14M downloads);append-only-vec@0.1.9published 07:37 UTC, yanked 09:25 UTC (4M downloads). All three added a single line toCargo.tomlnaming the typosquatproc-macro1as a dependency - Typosquat dropper crate:
proc-macro1@1.0.107published 07:11 UTC by compromised accountdtolney(a typosquat of the legitimateproc-macro2, one of the most-used Rust crates in existence - soproc-macro1reads as "obviously legit" to a scanner keyed to substrings). The library source ofproc-macro1is a genuine copy of proc-macro2 source so cargo builds still complete cleanly; all malice sits insidebuild.rs. Variantproc-macro-enwas also seen in the same window - Payload behaviour (executed during
cargo build, not at runtime): the maliciousbuild.rsreconstructs C2 URLs from base64-encoded fragments, disables TLS verification via a rustlsAcceptAllverifier, downloads a target-specific binary from23.254.165.112:9089under the namerust-crate_0.1.0/_0.2.0/_0.3.0/_0.4.0(matched to Linux x86-64, Windows x86-64, macOS x86-64, macOS ARM64), then invokes it with C2 address23.254.165.112:443asargv[1]. On Unix the binary is dropped to/tmp/rust-setupand spawn-detached; on Windows the dropper writes%TEMP%\rust-setup.ps1andrust-setup-launch.vbs, launches viawscript.exewithCREATE_NO_WINDOW, and usesstd::mem::forget()to escape the Cargo build job object so the payload survives after the build finishes - Blast radius via transitive dependency chain:
arrayrefis a foundational primitive used byblake3, Rust GUI stacks (egui,eframe,iced,tiny-skia,sctk-adwaita,winit), and Ethereum/Solana components. Wiz observed it in ~35% of environments they scanned, and ~75% of environments where any Rust is present - so an org that builds any modern Rust code has a high probability of pullingarrayreftransitively even without a direct[dependencies]entry. Any host that rancargo build,cargo update,cargo check, or CI resolution against these crates between 07:11 and 09:25 UTC on 2026-08-20 executed the payload - Attribution: Wiz reports significant overlap with DPRK / Lazarus supply-chain campaign infrastructure (naming and payload patterns previously seen in Famous Chollima / Contagious Interview activity). Both publishing accounts (
droundyfor arrayref,dtolneyfor proc-macro1) appear to have been compromised via credential theft rather than being sock puppets. To create update pressure towardarrayref@0.3.10, the attacker also yanked all prior versions from0.3.5to0.3.9so cargo resolvers rolling forward from earlier ranges landed on the malicious version - the Rust Security Response Team subsequently un-yanked those clean releases - Detectability: passive scanners that hash only
arrayref's own source code miss this attack completely - the malicious change is a single added line inCargo.tomlnaming a real-looking dependency, and the payload lives in a separate crate. Detection requires resolving the full dependency graph and flagging previously-unseen crate names, or monitoringbuild.rsexecution for outbound HTTP to fresh IPs
What to do
- 1Grep every
Cargo.lockin your monorepo, on every developer laptop, and in every CI build cache for:arrayref = "0.3.10",internment = "0.8.7",append-only-vec = "0.1.9", or any version ofproc-macro1orproc-macro-en. Presence of any of these under the resolved 2026-08-20 07:11-09:25 UTC window is proof the build ran the dropper - 2On any host that resolved (via
cargo build,cargo update,cargo check,cargo test, or CI) any affected version during that window: assume the host is compromised. Rotate every credential the build shell could reach - crates.io API tokens (~/.cargo/credentials.toml), npm tokens the same runner also touches, GitHub Actions PATs, cloud provider keys, SSH keys, browser saved logins on developer laptops - 3Detection artifacts: look for
/tmp/rust-setupon Unix (executable, present after the build),%TEMP%\rust-setup.ps1andrust-setup-launch.vbson Windows, and outbound connections from the build host to23.254.165.112:9089or23.254.165.112:443. On a shared CI runner also check for the payload survivor process detached from the cargo job - 4Update to clean versions:
arrayref<= 0.3.9 (the Rust Security Response Team un-yanked these after the attacker yanked them; they are safe),internment<= 0.8.6,append-only-vec<= 0.1.8. Do NOT installproc-macro1orproc-macro-en- both are attacker crates with no legitimate use - 5Add both
proc-macro1andproc-macro-ento anycargo-denydeny-list or SBOM alerting policy so future re-publishes under the same slug fire immediately - 6Systemic hardening: enable
cargo --frozenin CI so lockfile changes are explicit; considercargo vetorcargo crevfor a signed-audit chain against foundational crates; disable arbitrarybuild.rsexecution where feasible (harder for GUI/native builds but viable for pure-Rust crates) - 7IOC hashes (SHA-256) for endpoint/AV blocklists:
arrayref-0.3.10=25ad700976873c76af785cb99b33c48db7df8b81f21d1e9e06b3676b9a9373ae;proc-macro1-1.0.107=61198155da51b838772eecf5bfaac6cbc4dcc388dccc56658fc28a8e831b34d4
References
- RustSecRUSTSEC advisory-db issue #3161 - arrayref 0.3.10 executes a remote payload at build time via typosquatted proc-macro1github.com
- Rust ProjectSupply chain attack on arrayref - Rust Blog (official post-incident writeup by the Rust Security Response Team)blog.rust-lang.org
- SocketPopular Rust Crates Compromised in Build-Time Supply Chain Attack - Socket AI Scanner detectionsocket.dev
- WizRust Supply Chain Attack on arrayref: Significant Overlap with DPRK Campaigns - Wiz threat attributionwiz.io
- BleepingComputerHackers poison arrayref Rust crate to push infostealer malware - BleepingComputerbleepingcomputer.com
- StepSecurityRust Supply-Chain Attack: arrayref, internment, and append-only-vec Poisoned by the proc-macro1 Build-Time Dropper - StepSecuritystepsecurity.io
- The Hacker NewsRust Supply Chain Attack Puts Build-Time Malware in Crates with 245 Million Downloads - The Hacker Newsthehackernews.com
- The RegisterHackers poison popular Rust crates to steal developers' credentials - The Registertheregister.com
- AikidoTwo popular Rust crates arrayref and append-only-vec compromised in supply chain attack - Aikido Securityaikido.dev
- SafeDepMalicious Rust Crate arrayref Runs a Build-Time Payload - SafeDepsafedep.io
- SemgrepRust Crates arrayref & append-only-vec Compromised via proc-macro1 - Semgrepsemgrep.dev