Phorion, a threat research firm, published an advisory on October 30 describing a backdoor in the official Claude Code for VS Code extension bundle distributed through the Cursor Marketplace. The affected versions are 2.1.312 and 2.1.313. Cursor has pulled both. The implant plants an attacker-controlled Ed25519 public key in ~/.ssh/authorized_keys, opens a reverse SSH tunnel to 134.209.82[.]225, and sets up reboot-surviving persistence on macOS, Linux, and Windows. Cursor’s own security notice confirms the affected versions for macOS and Windows.
This is the most consequential AI coding tool incident of the year, and the least interesting part of it is the malware.
The extension is the attack surface nobody audits
Cursor’s marketplace serves extensions for an editor that a large share of working engineers now use as their daily driver. Extensions run with the permissions of the IDE and the user. That means a backdoored extension gets local files, source code, and developer tooling the moment its module loads. Phorion’s write-up is precise about the mechanism: the compromised extension.js begins with an injected immediately invoked function expression prepended to the minified bundle. The rest of the file looks normal, with standard activate and deactivate exports and UI code. The injected prefix pulls in child_process, fs, os, path, http, and crypto, and executes as Node loads the file, before the extension’s normal activate callback runs. The user does not have to interact with the extension for the payload to fire.
That last sentence should be read twice. Installing the extension is the exploit. There is no prompt to click through, no command to run, no trust dialog that changes the outcome.
What the payload actually does
Stage one appends a public key commented svc-telemetry to authorized_keys, with 0700 on the directory and 0600 on the file. The check for an existing key looks for the string svc-telemetry rather than the key fingerprint, so an investigator relying on the comment alone can be misled. Stage two writes an unencrypted OpenSSH Ed25519 private key, commented svc-telemetry-tun, to a temp file named .stk_ plus the first ten characters of the MD5 hash of hostname and home directory. It then opens an outbound connection with -R *:0:localhost:22, asking the attacker’s server to allocate a listening port and forward traffic back to the victim’s local port 22. The tunnel runs with -N, host-key checking disabled, known_hosts ignored, keepalives at 30 seconds, and ExitOnForwardFailure on. If autossh is installed it uses that; otherwise plain ssh. The whole thing sits in a detached retry loop that sleeps 60 seconds between attempts, so it survives closing the IDE.
Stage three is persistence. On macOS it writes a LaunchAgent named com.apple.sysmond.plist into ~/Library/LaunchAgents/ with RunAtLoad and KeepAlive both true, then loads it via launchctl. On Linux it writes ~/.config/.smt and ~/.config/.smtk and adds an @reboot crontab entry. On Windows it tries a scheduled task named SysMon running as SYSTEM, falling back to sysmon.cmd in the Startup folder. Stage four beacons hostname, username, platform, architecture, home directory, working directory, global Git email, public IP, and up to 40 environment variable names matching /KEY|[TOKEN](/glossary/token-tokenization)|SECRET|PASS|AWS|GCP/i back to the operator.
The environment variable reconnaissance is the part that should worry AI teams specifically. Developer machines are where API keys live. A filter for KEY, TOKEN, SECRET, AWS, GCP in a working engineer’s environment is a filter aimed at cloud credentials and model provider keys. The advisory says it captures variable names, not values. The distinction matters less than it looks: names tell an operator what to go back for.
Two of three platforms are broken, which is luck, not design
The macOS path has an implementation bug worth understanding because it is the kind of thing that will get fixed next time. The script runs systemsetup -getremotelogin without elevation and tests the output against /Off/i. Run as a standard user, systemsetup refuses, prints “You need administrator access to run this tool… exiting!” to stdout, and exits with status 0. The regex does not match, so the script skips the sudo -n systemsetup -setremotelogin on step entirely. It treats “I cannot check whether SSH is off” as “SSH is already on.” On a Mac without Remote Login already enabled, the inbound path is dead. The keys and persistence still land.
The Windows path has its own bug: the PowerShell service setup command is passed through a helper that hardcodes /bin/sh, which goes nowhere on a standard Windows install. The Linux path has a crontab check that can wipe existing user cron jobs on repeat runs.
None of this is a defense. Phorion is explicit: if the user already had Remote Login enabled, or turns it on later, the backdoor is ready and waiting. The bugs reduce blast radius; they do not remove the implant.
The payload fires before the extension’s own activate callback runs. Installing was the exploit.
The real finding is about trust chains in AI tooling
Every serious AI coding product now ships as a plugin into someone else’s editor. Claude Code runs inside VS Code and Cursor. Copilot runs inside both. Codex runs wherever the IDE lets it. The distribution layer is a marketplace, and marketplaces have historically been the softest part of any software ecosystem. The npm ecosystem learned this the hard way across a decade of typosquats and compromised maintainer accounts. VS Code’s own marketplace has had its share of malicious extensions. Cursor’s marketplace is younger, and the Claude Code extension is exactly the kind of high-trust, high-install package an attacker wants to compromise.
The question the industry has not answered is who audits the AI coding extensions. Anthropic builds Claude Code. Cursor distributes it. Both are now in the incident response loop. Neither has published, as of this writing, how the malicious 2.1.312 and 2.1.313 bundles got into the marketplace, whether the compromise was upstream at Anthropic or in Cursor’s ingestion, or what signing and provenance checks exist on either side. Phorion’s advisory does not answer it either. {/* TODO: verify whether Anthropic or Cursor has disclosed the root cause of the 2.1.312/2.1.313 compromise — searched phorion.io, cursor.com/blog, did not find authoritative statement */}
That gap is the story. A backdoor in a developer tool is bad. A backdoor in a developer tool whose distribution chain nobody can describe is worse, because it means the next one is already being built.
What builders should do this week
Search your fleet for Claude Code for VS Code 2.1.312 and 2.1.313. Check ~/.ssh/authorized_keys for a key commented svc-telemetry, and check the fingerprint rather than the comment. Look for .stk_ files in temp directories. On macOS, check ~/Library/LaunchAgents/ for com.apple.sysmond.plist. On Linux, check crontab -l for @reboot entries you did not write. On Windows, check for a scheduled task named SysMon. Rotate any cloud or model provider credentials that were present in the environment of an affected machine. Phorion’s advisory recommends incident response where use of the extension is discovered, and that is the right call.
The broader lesson is about the economics of AI tooling. The industry has spent two years optimizing for how fast a coding agent can be dropped into an existing workflow. It has spent almost none of that time on how the agent’s distribution channel is secured. Marketplaces optimize for install velocity. Supply chains optimize for nothing in particular until they break. The Claude Code extension was on the Cursor Marketplace because that is where the users are, and it was compromised because that is where the users are.
Cursor pulled 2.1.312 and 2.1.313. The next question is what gets pulled next, and whether anyone can say in advance which extensions deserve to be trusted.