← All posts

Eighty-Six Minutes: The Attack Your Tools Will Tell You Never Happened

On Thursday morning, between 7:11 and 9:25 UTC, someone with stolen credentials published poisoned versions of three small pieces of software that sit underneath a large share of the world's Rust applications. The largest of them, a utility called arrayref, has been downloaded roughly 245 million times. The cloud security firm Wiz reports finding it in about three-quarters of the environments where Rust is present at all.

The malicious versions were online for 86, 90, and 107 minutes respectively. Then they were gone — deleted, not merely flagged.

That last detail is the one your board needs to understand, and I'll come back to it.

Nobody Attacked the Code

Here is what makes this incident different from the vulnerability stories your CISO usually brings to the audit committee.

There was not a single line of malicious code in arrayref. The library source was untouched. What changed was one line in its manifest: a new dependency called proc-macro1, a near-perfect impersonation of a legitimate package called proc-macro2, published four minutes earlier by an account created that same morning under a name one transposed letter away from a well-known developer's.

That impersonating package shipped genuine, working source code. Every build succeeded. Every test passed. The weapon was a build script — a small program that runs automatically during compilation, with the full privileges of whoever is doing the building. It reached out to a server, downloaded a second-stage backdoor, and launched it in the background. Then it exited cleanly and the build went green.

arrayref had not added a dependency in its ten-year history. It didn't need one. It's an array-conversion utility roughly the size of a business card.

The compromised asset here was not software. It was a person's publishing credentials.

The Yank Was the Lure

The most instructive part of this operation, and the part I'd put on a slide, is what happened twenty-four seconds after the malicious version went live.

The same account began withdrawing every prior stable release — five of them, at roughly four-second intervals, in a cadence the researchers at StepSecurity describe as scripted rather than human. Withdrawing a release doesn't break anyone's existing build. What it does is make the build tool print a warning: the version you're using has been withdrawn, consider updating.

So a developer sees a scary new warning on a dependency with hundreds of millions of downloads, does the responsible thing, runs the update command — and lands on the only remaining version, which is the poisoned one. The original researcher who reported the incident says this is precisely how they were hit.

The attacker turned the ecosystem's own safety warning into the delivery mechanism. Diligence was the attack path. I want executives to sit with that for a moment, because it cuts against the instinct that more alerts and faster patching are always the answer.

Why Your Dashboard Says Everything Is Fine

Now the part I flagged at the top.

Because the malicious versions were deleted from the registry rather than marked as vulnerable, standard dependency-scanning tools report a clean result for a project that pinned a poisoned version. StepSecurity's analysis is blunt about this: automated tooling will not flag it for you. Worse, a build machine with a warm local cache — or a company that keeps a local copy of its dependencies, which is generally considered good practice — will keep compiling the payload offline even though the version no longer exists anywhere on the public internet.

This is the compliance-versus-security gap in a single fact. Your scanner is green. Your dashboard is green. Your quarterly attestation says you had no findings. And a developer laptop in your organization may have spent Thursday morning beaconing to a rented server.

The Rust Security Response Team, to their considerable credit, moved fast and published advisories stating they found no evidence that any malicious version was actually used. But in the public advisory thread where the incident was first reported, a developer described being infected and named the server their machine was calling. Both statements can be true at once. "No evidence of use" is a statement about what the registry can see. It is not a statement about what happened inside your build pipeline, and no outside party can make that statement on your behalf.

Who Did It, and Why That Matters to a Board

Wiz reports — based on shared command-and-control infrastructure, a matching server-side certificate signature, and the same hosting provider address range used in two earlier attacks on JavaScript packages — that this campaign overlaps significantly with operations attributed to North Korean actors. Microsoft attributed one of those earlier attacks to a group it calls Sapphire Sleet; Google's threat intelligence group attributed the other to an actor Mandiant links to North Korea. Read that carefully: it is infrastructure overlap, not a confession, and as of this writing no vendor has formally attributed this incident to a named actor.

But the attribution matters for one governance reason. A criminal crew running ransomware wants your money and will tell you they're there. A state-sponsored crew running credential theft through build systems wants persistence and quiet. The second kind does not announce itself, does not trigger your incident response plan, and does not create a materiality determination you can date. It just sits in the pipeline that produces your software.

If your cyber risk conversation is organized entirely around "what happens when they lock our files," you are governing for the loud version of the threat.

What to Ask Your CISO This Week

Three questions. None require you to understand a build script.

First: Did any of our machines — developer laptops, build servers, contractor systems — compile Rust code between 7:11 and 9:25 UTC on August 20? The honest answer for many organizations will be "we don't know," and that answer is itself the finding. If you can't reconstruct what your build systems did on a given morning, you cannot scope any supply chain incident, this one or the next one.

Second: Would our tooling have caught this? Push past yes. The specific follow-up is whether your scanners rely on published advisories — because in this case the malicious versions were deleted before advisories were issued, which means the tooling reports clean. This is the difference between a control that works and a control that reports.

Third: What is our waiting period on new versions of outside code? The malicious releases lived for under two hours. Any organization with a rule that says "we don't consume a dependency version until it has been public for a few days" experienced this attack as a non-event. Google's threat intelligence group formally recommended exactly this — cooling windows on newly published third-party components — in a report published three weeks before the attack, and GitHub shipped a three-day delay as a default for one of its own tools in July.

Here is the part that should sharpen the question rather than answer it: Rust's build tool has no such feature shipped. A proposal to add one entered its final review period on August 18 and was still unmerged when the attack landed on the 20th. So the honest answer for a Rust shop today is that this control has to be built or bought, not switched on.

That is still the question I would press hardest. Most of the expensive controls we debate at the board level are attempts to detect an attacker who is already inside. A waiting period keeps you out of the blast radius entirely, it is a policy decision rather than a technology purchase, and the person who has to sponsor it is probably reading this.

Eighty-six minutes is not a window your quarterly vendor review is going to catch. It is, however, exactly long enough.