# Rust Supply-Chain Attack: arrayref, internment, and append-only-vec Poisoned by the proc-macro1 Build-Time Dropper

Compromised crates.io account published arrayref 0.3.10, internment 0.8.7, append-only-vec 0.1.9 injecting typosquat proc-macro1 whose build.rs drops and executes a remote payload at compile time.

- Payout: Real-world hack
- Severity: critical
- Program: crates.io
- Analysis by: StepSecurity
- Disclosed: 2026-08-22
- Write-up quality: 8/10
- Original: https://www.stepsecurity.io/blog/arrayref-rust-crate-supply-chain-attack
- Library page: https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-arrayref-rust-crate-supply-chain-attack
- Tags: area:oss domain:oss impact:internal-access impact:rce kind:incident platform:threat-intel sev:critical tech:ci-cd tech:rust technique:recon technique:source-review vuln:dependency-confusion vuln:rce vuln:secrets-leak

**Target:** Rust crates on crates.io; Cargo build scripts (build.rs) executed at compile time
**Root cause:** A compromised maintainer account added a single new dependency (typosquat proc-macro1) to zero-dependency crates; proc-macro1's build.rs is a cross-platform dropper that fetches and executes a stage-2 binary with TLS verification disabled. Build scripts run with the builder's full privileges at compile time, so no library code needs to be called.
**Steps:**
1. Attacker creates GitHub/crates.io account `dtolney` impersonating `dtolnay`; publishes clean decoy `proc-macro1@1.0.106` (copy of proc-macro2, no build.rs).
2. Publish `proc-macro1@1.0.107` adding `build.rs` plus build-deps `base64`, `rustls`, `ureq`.
3. From compromised `droundy` account publish `arrayref@0.3.10` adding `proc-macro1 ^1.0.107` as sole normal dependency; repeat for `internment@0.8.7` and `append-only-vec@0.1.9`.
4. Yank arrayref 0.3.9/0.3.8/0.3.7/0.3.6/0.3.5 in a scripted burst so `cargo update` resolves only 0.3.10.
5. Victim runs `cargo build`/`cargo update`; Cargo compiles and executes proc-macro1's build.rs.
6. build.rs base64-decodes URL fragments to `https://23.254.165.112:9089/` and C2 `23.254.165.112:443`, fetches `rust-crate_0.x.0` over TLS with an AcceptAll cert verifier.
7. Unix: write `/tmp/rust-setup`, chmod +x, spawn detached with stdio nulled, `std::mem::forget(child)` to escape Cargo's job object. Windows: drop `rust-setup.ps1` + `rust-setup-launch.vbs`, launch via `wscript.exe`.
8. Build script exits 0; build succeeds; stage-2 connects to C2 and establishes persistence (systemd service, `$HOME/.config/AzureKits`, `MonoService`/`MonoXpc`).
**How found:** Researcher jhobern noticed arrayref 0.3.10 — a decade-old zero-dependency crate — suddenly declaring a dependency on a same-day typosquat `proc-macro1`; registry index diff showed the manifest change and the three added build-deps (base64/rustls/ureq) that constitute a downloader toolkit. Yank burst and same-timestamp updates on internment/append-only-vec confirmed account compromise.
**Exploitation:** Supply-chain compromise of a maintainer's crates.io credentials. Malicious releases were live 86/90/107 minutes; any lockfile created or refreshed in that window resolved the poisoned version and executed the dropper at build time with the builder's privileges, giving access to SSH keys, cloud tokens, CI secrets and signing keys. Yanking clean versions weaponized Cargo's yanked-version warning to herd developers into `cargo update` toward the poisoned release.
**Escalation:** Second dropper crate `proc-macro-en` held in reserve with identical build.rs; four additional attacker-owned crates (`aovine`, `arone`, `aronenao`, `tinymember`) staged two days earlier; `internment` depends on `append-only-vec` so one resolve could pull two poisoned crates.
**Insight:** Registry index metadata alone fingerprints this class: a zero-dependency crate gaining its first dependency, especially one named like a well-known crate and published the same day, is a high-confidence compromise signal. Also treat 'yanked version' warnings as a social-engineering vector — a sudden mass-yank of clean versions is an upgrade lure, not a maintenance chore.
