The Take — The Cursor backdoor failed by luck, not by design

Share
The Take — The Cursor backdoor failed by luck, not by design

For eleven hours on Thursday, Cursor's marketplace served a tampered build of Anthropic's own Claude Code extension, and the thing that stopped it from becoming an SSH backdoor was not a control. It was a bug in the malware. Two bugs, in fact. That is the part of this story I cannot get past: the supply chain for AI coding tools is currently defended by the incompetence of strangers, and nobody in the chain has proposed a defense that would work against a stranger who is competent.

The facts are worth restating tightly, because the argument depends on them. Versions 2.1.312 and 2.1.313 of the anthropic.claude-code package shipped to macOS and Windows users from about 2:27am to 1:35pm Pacific on October 29, per Cursor's incident notice. The payload fingerprinted the machine, swept environment variables for names containing key, token, secret, password, AWS and GCP, then appended an attacker-controlled key labelled svc-telemetry to the SSH authorized-keys file and opened a reverse tunnel that retried roughly once a minute. Persistence came three ways: a macOS LaunchAgent wearing Apple's own naming convention, a Windows scheduled task called SysMon that tries to run as SYSTEM, and a reboot cron entry on Linux. That last one matters. The compromised builds shipped for two platforms; the payload was prepared for three.

What actually stopped it

Nothing that was supposed to. Turning on remote login needs administrator rights the extension did not have. On macOS the check for whether remote login was enabled returns an error instead of "off" when run without elevation, so the enabling step was skipped entirely. On Windows the OpenSSH install was routed through a Unix shell that does not exist. BleepingComputer's teardown and a separate analysis by Phorion reach the same conclusion, which is that the backdoor very likely never opened.

The key was still added. The persistence scripts still landed. Cursor's own remediation advice says uninstalling the extension may not be enough, and asks anyone who ran the build to rebuild the host and rotate credentials from a clean machine. So the honest scoreboard reads: attacker reached the machine, planted the persistence, exfiltrated the reconnaissance, and was denied only by its own mistakes at the final step.

The number everyone is quoting belongs to the company

Cursor put the exposure at "at most 5,000 users" in a post on X, and that figure has been repeated since as if it were a measurement. It is an upper bound from the party that owns the download logs, and its smallness is doing a lot of work in how this incident is being filed: a scare, contained, eleven hours, five thousand developers. Maybe. But the count is unverifiable from outside, and the more important number is zero: the number of public explanations of how a modified build got published under Anthropic's publisher identity and, by all appearances, Anthropic's version number.

That gap is not a loose end, it is the whole case. If someone obtained publishing access to the listing, then the marketplace's identity check was intact and useless. If the artifact was swapped somewhere between the build and the CDN, then identity was never the failure. If Anthropic's own build pipeline was reached, then nothing Cursor could have added at the listing level would have helped. The Hacker News has pressed the same question, and until one of those three answers is on the record, every proposed fix is being sold without a diagnosis. I will take the proposals that work under all three.

The fix is a property of the artifact, not a bigger review queue

Two mechanisms hold regardless of how the build got in.

The first is a transparency log for published builds: an append-only, public record of the hash of every artifact a publisher ships, written by the build system rather than the listing. A version that no build produced has no entry, and the client can refuse it before install. This is not exotic. It is what package ecosystems have been slowly assembling for years under the heading of provenance, and it fails exactly one of the three scenarios above, the one where the publisher's own build was compromised. Even then it converts an eleven-hour mystery into an attributable record.

The second is a rollout that is not instantaneous. Eleven hours to the full installed base is the amplifier in this story, not the compromise. A staged ramp with a soak period, plus a kill switch that halts distribution on the first anomaly report, would have confined a trojanized patch release to a small cohort instead of everyone who opened their editor that morning. Cursor did eventually pull the marketplace entirely and rotate keys, which is the right response executed at the wrong end of the timeline.

And the tame version, for the individual developer: an extension that can read your cloud credentials should not update itself silently. Pinning versions and prompting on updates is annoying, and the annoyance is proportionate to what the tool can reach.

The counter-case, and it is better than it looks

The strongest objection is that the response was actually good. Researchers tore the build apart within hours; Cursor took the marketplace offline, rotated keys, rebuilt, reopened, and worked with a hosting provider to kill the attacker's server. An ecosystem that contains a supply-chain attack inside a day is an ecosystem working. The payload was also sloppy in a way that suggests commodity crime, not a capable adversary, which argues the current posture is adequate against the threats that actually show up.

The second objection is scale. Reviewing every update is a filter, and filters are priced in attacker iterations: submissions are cheap, rejections are cheap, and the attacker only needs one pass. Human review cannot be the primary control, and pretending otherwise produces security theater with a queue.

The third is that staged rollouts cost something real. Auto-update exists because users do not update, and a fix parked in a canary for a week is a known-vulnerable extension on most machines for a week. Delay is paid in the same currency the attacker spends.

Why the take still holds

Because the counter-case defends the review queue, and I am not asking for one. A signature check and a log lookup happen on the client, at machine speed, for a fraction of a cent, and they do not care how many updates are published. The scaling argument kills human review and leaves provenance untouched.

Because the containment was a rescue, not a control. Rescue depends on someone noticing, and noticing depends on the attack being conspicuous. The next one will not append a key with a helpful label and retry on a fixed interval.

And because the asset changed. In 2016 the npm attack surface was a build step. In 2026 it is an editor extension that holds a repository, a shell, an SSH config and a cloud token, on a machine that a developer has told their employer is a trusted endpoint. The asymmetry between what the update can reach and what the update must prove is the largest unclosed gap in the AI developer stack, and this month alone the Claude name has been used as bait twice, the earlier attempt being fake installers riding Bing ad redirects. As our report on Thursday's incident put it, the publish path gets a status page while the model gets a benchmark. Eleven hours of full distribution is what a status page buys you.

What would change my mind

Show me a marketplace that signs artifacts, logs their hashes and stages rollouts, and still served a trojanized build under the true publisher's identity within the hour, and I will concede that provenance is theater and the only lever left is vetting budget and response speed. Show me evidence that a soak period materially delays critical extension fixes because users do not update manually, and the rollout half of my argument gets weaker; I would keep the log and drop the ramp. And if it turns out the tampered build carried a valid, correctly attested artifact out of Anthropic's own pipeline, then the argument moves upstream entirely, to build hardening, and every marketplace control I have named is a check written against the wrong party.

Until one of those lands, the record stands where Cursor left it: an attacker got eleven hours of distribution inside a trusted publisher's identity, and the reason your machine is fine is that the attacker wrote a bad check for administrator rights.

Would you notice if your editor extension shipped a build nobody built? Write to us via our contact page.

Get SiliconNoon in your inbox

One email a day with the AI stories that matter — what happened, the numbers, and why it matters. No spam, unsubscribe in one click.

Read more

How to — stop an agent before it burns your budget

How to — stop an agent before it burns your budget

An agent that runs unattended fails in a way a chat window never does: it fails expensively. The job here is to make the worst case of any run a number you know before you press go — and to have the run stop itself the moment it stops making progress. Most teams discover this the hard way. A task that should take twelve steps takes four hundred, half of them re-asking the same question in slightly different words, and the invoice arrives two days after the incident.

How to — review AI-written code before you merge it

How to — review AI-written code before you merge it

You want to merge AI-written code without reading every line of it — and still be able to say, out loud, what it does and what happens when it breaks. That is a review job, and it is mostly about reading the right parts in the right order. Cockroach Labs ran its codebase like a teaching hospital for five months and reports merging well over a million lines of code with seven total reverts — a run where no agent's plan moved without a human-signed review first (we covered Coding agents as a…

How to — estimate what an AI feature will cost before you ship it

How to — estimate what an AI feature will cost before you ship it

You want one number you can defend in a planning meeting: what each completed job on your feature costs, and what a month of it costs at launch volume. This is a measurement job, not a guess — a morning with your real prompts beats any pricing page. 1. Run 20 real requests and keep the usage numbers. Not demo prompts — your actual system prompt, tool definitions, the documents you stuff into context, and a typical user message.