Artificial intelligence · 9 min read
Your coding agentis a supply chain.
For roughly 11 hours, a tampered build of the Claude Code extension shipped a persistent SSH backdoor from Cursor's marketplace. Here is exactly what the payload did, and why your developer fleet is a softer target than your cluster.
In short
- Versions 2.1.312 and 2.1.313 of the
Anthropic.claude-codepackage on Cursor's marketplace executed an SSH backdoor at module load, before the extension'sactivate()callback. Around 5,000 developer machines are believed affected. - The payload appended an Ed25519 key labelled
svc-telemetryto~/.ssh/authorized_keys, installed persistence (LaunchAgent,@rebootcron, scheduled task) and beamed host inventory to a command server. - Two bugs in the malware limited the damage — not anyone's security stack. The lesson is not "AI extensions are dangerous", it is "an IDE marketplace is a package registry running with user privileges".
The real problem: an extension runs as you
An IDE extension is not a sandboxed browser plugin. It is Node.js code loaded inside the editor process, with the permissions of the user who installed it: read access to every repository on disk, to ~/.ssh, to environment variables, to Git credentials, to network sockets. On a 2026 developer laptop that is the most valuable asset in the company — usually more than the staging cluster.
For years this attack surface stayed theoretical because extensions were few and published by their own vendors. Coding agents changed the scale: every developer now installs, updates and occasionally trials several extensions per month, often from third-party marketplaces, with auto-update on. That is the npm threat model, except the package gets full access to source code and secrets.
So the October 29 incident is not an isolated accident. It is the first large-scale public demonstration of what "installing an agent" actually means: the model, the prompt and the tool loop are only the visible layer. The attack vector is the package that carries them.
11 hours, two versions, 5,000 machines
The timeline is documented in Cursor's security notice and in Phorion's endpoint analysis, which detected the activity on customer machines. Between 2:27am and 1:35pm PT on October 29, a modified build of the official Claude Code extension was published to Cursor's VS Code marketplace for macOS and Windows. Per Kevin Beaumont, Cursor estimates roughly 5,000 developer systems were impacted. Cursor pulled the package, shut the marketplace down as a precaution, rotated its keys and had the attacker's server taken offline; Anthropic stated it had no part in building or publishing the tampered build.
Two versions are in scope: 2.1.312, then 2.1.313. The follow-up 2.1.314 removes the payload from the package — it does not clean machines that already ran it. That is the part most summaries missed: the update closes the door, it does not remove the intruder.
Anatomy of the payload
The technical detail is worth reading, because it shows how little sophistication was required. The compromised extension.js begins with an IIFE prepended to the minified bundle. It pulls in child_process, fs, os, path, http and crypto, and executes as soon as Node loads the file — before the extension's activate() callback. No user interaction required: opening the editor is enough.
The sequence after that is textbook:
- Recon. Collect hostname, username, OS, architecture, home path, environment variable names, working directories, configured Git email and public IP. The inventory is POSTed to
/beaconon port 8099. - Access. Append an attacker-controlled Ed25519 public key to
~/.ssh/authorized_keys, with0700/0600permissions. The key carries the commentsvc-telemetry— useful for the attacker's own bookkeeping, and for your detection. - Tunnel. Attempt to enable the local SSH service (
systemctlon Linux, Remote Login on macOS, OpenSSH Server on Windows) and open a reverse SSH tunnel, retried roughly every 60 seconds. - Persistence. On macOS a LaunchAgent at
~/Library/LaunchAgents/com.apple.sysmond.plistrunning/bin/sh ~/.config/.smt; on Linux an@rebootcron entry; on Windows aSysMonscheduled task with a Startup-folder script as fallback.
The indicator table, if you are hunting:
| Artefact | Platform | Role |
|---|---|---|
~/.ssh/authorized_keys (comment svc-telemetry) | All | Attacker's Ed25519 key |
$TMPDIR/.stk_<10 hex> | All | Tunnel private key in the temp directory |
~/.config/.smt and ~/.config/.smtk | macOS, Linux | Persistence script and recreated key |
~/Library/LaunchAgents/com.apple.sysmond.plist | macOS | Login-time LaunchAgent |
@reboot cron entry pointing at ~/.config/.smt | Linux | Restart persistence |
SysMon task plus sysmon.cmd | Windows | Scheduled task and Startup fallback |
The two bugs that saved the day (by accident)
The most interesting part of this story is that the attack largely failed because of development mistakes, not defences. On macOS the script checks Remote Login state with systemsetup -getremotelogin without elevation. Run as a standard user, that command prints "You need administrator access to run this tool" and exits with status 0. The /Off/i test therefore never matches, and the SSH enablement step is skipped entirely. On Windows, the service install path goes through a helper that hardcodes /bin/sh, which does not get far on a machine without a POSIX shell.
Net effect on most hosts: the SSH key and the persistence were planted, the beacon fired, but interactive access failed because no SSH daemon was listening. That does not make the incident benign — recon and persistence both succeeded, and credential access over a later foothold was still on the table. It says something more useful though: the gap between a major incident and a catastrophe was two lines of code. Do not count on that next time.
Detect and remediate without an EDR
The baseline check is one command. On macOS and Linux:
grep -qs svc-telemetry ~/.ssh/authorized_keys && echo "key found" || echo "not impacted"
On Windows, check $HOME\.ssh\authorized_keys and C:\ProgramData\ssh\administrators_authorized_keys in PowerShell. Then sweep for the artefacts above: ~/.config/.smt, ~/.config/smt.cmd, com.apple.sysmond.plist, the SysMon task, an @reboot cron entry, and .stk_* files in the temp directory. An antivirus without the sample in its database will not help you; these paths will.
If a host is positive, order matters: isolate it from the network, remove the key and the persistence mechanisms, kill tunnel processes, then from another machine rotate every credential reachable from that host — Git tokens, cloud keys, browser sessions, secrets sitting in environment variables. The initial collection only grabbed variable names, but nothing guarantees a later foothold would not widen it. And rebuild is the safer option when the host had production access.
Production checklist
- Treat the IDE marketplace as a package registry. Pin and inventory versions, disable auto-update on machines holding production secrets, and mirror approved extensions internally.
- Alert on
svc-telemetryand the artefact paths. Any change toauthorized_keysoutside your onboarding flow should page someone. Cheaper than an EDR, and it catches benign cases too. - Separate the machines. The laptop that holds production cloud keys should not be the one where you trial three agent extensions a week.
- Rehearse rotation. This kind of incident is only clean if you know which credentials were reachable. An inventory of secrets per machine, or remediation is guesswork.
- Do not confuse updating with cleaning.
2.1.314removes the payload from the package; it deletes neither the key, nor the LaunchAgent, nor the scheduled task already installed.
Need help designing reliable AI workflows, auditing an LLM architecture, or training your engineering team? See how we work at Kaleido-Lab.