The Yank Funnel and the Build That Runs Itself

Friday 21 August 2026 topic: yanking as a dependency funnel and Cargo's unsandboxed build-time trust gap

This is a lead editorial illustration for a narrative piece about supply-chain manipulation via dependency resolution mechanics — a conceptual/metaphorical subject with no numeric…

The trick isn’t that someone slipped malware into Rust’s registry, it’s how they made sure you’d pick it. I have watched this industry treat the package manager as a filing cabinet when it’s really a set of rails, and this week someone proved they understand the rails better than we do.

A popular little crate called arrayref suddenly grew a dependency it had never had before, a typosquat of proc-macro2 published four minutes earlier by an account impersonating its real author.1 Version 0.3.10 added a dependency on the typosquatted proc-macro1 whose build script downloads and runs a remote binary while the project compiles.2 The script reassembled its server address from base64 fragments and fetched an architecture-specific binary over TLS that accepts any certificate without validation, then ran it detached from the build.2 You did not need to call the crate at all, because Rust build scripts run at compile time and simply building any project whose lockfile resolved that version was enough to detonate the payload.1 This lot paired the dropper with a piece of social engineering aimed not at you but at Cargo itself.

The attacker yanked the legitimate recent versions, leaving only the poisoned 0.3.10 as the non-yanked release, which the team later fixed by removing the malicious version and unyanking the legitimate ones.3 That yank makes Cargo print a warning nudging developers toward the only version that is not yanked, which was the malicious one.2 It is not a buffer overflow, it is a nudge. Cargo is often said to be safer than npm because adding a dependency does not run custom code the way npm install scripts do.4 True enough, but it misses the point this attack proves: the code does not run when you add it, it runs when you build it, and in Rust you build all the time. The Rust Security Response Team verified the crate had a build script downloading a malicious payload and removed it along with several other typosquatted crates.3 It was broader than one crate, two more crates owned by the same maintainer were published with the same dropper and several attacker-owned crates were deleted.1

Here is the pushback I keep hearing, and it is half right. The team was blunt: “We do not believe the author of arrayref to be acting maliciously, but their computer or credentials are likely compromised, and we are attempting to contact them.”3 That cuts against the easy villain story, but it makes the systemic point worse. If you can steal one maintainer’s token and then use the registry’s own yank semantics to herd everyone onto your release, you do not need to own the ecosystem, you just need to own one trusted name for an afternoon. The community knows what the fix looks like even if we have not built it. One camp wants to use existing engines to sandbox build scripts and proc macros to protect build systems.4 Another wants a manifest allow-list where a dependency with a build script would cause a build error unless it is explicitly listed.5 A stopgap is already on offer as a near drop-in replacement that runs cargo commands in a Docker container to isolate potentially malicious code from the host environment.6

My take is this. The yank funnel worked because Cargo’s trust model still treats build scripts as trusted compiler help, not as third-party code running on your machine with your secrets. For years we told ourselves we were safer than the npm crowd because we do not run install scripts, and that story was comforting and technically true and completely beside the point. This attack did not need an install script, it needed a build, and yank is a built-in well-meaning feature that turns a warning into a shove. Until build scripts and proc macros are sandboxed or explicitly allowed, every widely used crate is a potential dropper if its publisher token leaks. The fix is not to tell developers to read diffs more carefully, it is to stop executing strangers’ code unsandboxed at build time and to stop letting anyone use yanking to make the malicious version the path of least resistance.

Sources

How this was made
  • 01-research z-ai/glm-5.2 $0.215
  • 03-annotate z-ai/glm-5.2 $0.052
  • 04-nominate deepseek/deepseek-v4-pro $0.007
  • 05-select google/gemini-3.7-flash $0.003
  • 06-write meta/muse-spark-1.2 $0.053
  • 08-visualise anthropic/claude-sonnet-5 $0.037

total $0.368

What each stage does, drawn out →