A backdoor in the Claude Code extension, and the window that does not matter anymore

Fake builds of Anthropic's Claude Code extension sat on Cursor's marketplace for about 11 hours on October 29, reaching at most 5,000 users. What the payload did, the bugs that blunted it, and why one infected Mac kept beaconing 8 hours after the window closed.

A backdoor in the Claude Code extension, and the window that does not matter anymore

Hacker News spent October 30 watching one story: tampered builds of the official Claude Code extension appeared on Cursor's VS Code extension marketplace and stayed up for about 11 hours. The vendor notice puts the window between 2:27 a.m. and 1:35 p.m. Pacific time on October 29 and estimates at most 5,000 users installed the malicious versions. The thread collecting the fallout passed 850 points with more than 500 comments.

Anthropic did not build the malicious packages. The tampered extension carried the project's name, its publisher identity, and all of its normal behavior, with one injected block doing the damage. Microsoft confirmed the same packages never appeared on the Visual Studio Marketplace or on the official npm package, and Anthropic told Microsoft its own systems were not compromised. Everything published so far points to Cursor's marketplace as the single compromised channel.

What the payload did

The injected code runs the moment the extension module loads. No click, no prompt. According to Phorion's teardown and Microsoft's analysis, the sequence goes like this. It collects host details: hostname, username, OS, architecture, home and working directories, configured Git email, and public IP. It sweeps environment variable names for KEY, TOKEN, SECRET, PASS, AWS, and GCP, keeping up to 40 matches. The names leave the machine. The values stay.

It appends an attacker-controlled Ed25519 public key, labeled svc-telemetry, to the user's authorized_keys. It tries to switch on the local SSH service. It opens a reverse SSH tunnel to 134.209.82.225, forwarding an attacker-allocated port back to port 22 on the victim's machine, and a retry loop fires every 60 seconds.

It survives reboots: a LaunchAgent named com.apple.sysmond on macOS, a scheduled task named SysMon requesting SYSTEM on Windows with a Startup-folder fallback, and a cron @reboot entry on Linux. Cursor worked with the hosting provider to take the attacker's server offline, so the tunnel and the beacon currently connect to nothing.

Three bugs in the malware

The payload is plain JavaScript plus native tools. No zero-day, no kernel trickery, and it shows. Phorion counted at least three mistakes.

On macOS, the script runs systemsetup -getremotelogin without administrator rights to decide whether to enable SSH. As a standard user, macOS answers with "You need administrator access to run this tool... exiting!" and exits with status 0. The script only flips SSH on when the output says Off. A permission error is not Off, so it skips the step. The malware reads "I cannot check" as "already on".

On Windows, the service setup builds a PowerShell command and then passes it through a helper that hardcodes /bin/sh. That is a Unix shell path, on Windows.

On Linux, the crontab update has a bug in the opposite direction: on repeat runs, a flawed check can wipe existing user cron jobs.

None of this makes the campaign harmless. The SSH key gets planted, persistence gets installed, and the beacon still ships your host details. Expel responded to four customer incidents on this extension, and in one of them the tunnel connected out from a Mac whose user had no admin rights.

The window closed and the malware kept running

Cursor's remediation guidance scopes to installs made during the 11-hour window. Expel's incident data argues for a wider net. In one of their four cases, the first malicious activity fired at 04:45 UTC on October 30, about 8 hours after the window closed. The user logged in at 04:44, Cursor opened the same minute, and the payload ran as the extension loaded. The likely shape: downloaded during the window, first run on the next launch.

That Mac's tunnel kept reaching the attacker's IP for nearly 10 hours, from 04:45 to 14:29 UTC. The launch agent does not need the extension alive to do that. In another Expel case the tunnel was live and no attacker key turned up in authorized_keys, so the svc-telemetry grep everyone is running is a first check, not a clean bill of health.

Eight days after LiteLLM

The Cursor incident went live eight days after the LiteLLM one. On October 21, LiteLLM's own release pipeline pushed version 1.107.0 to PyPI and Docker with compiled malware inside, per the project's incident post. That one stole credentials and loaded remote execution tools. Expel responded to both classes of incident, and their summary of the gap is blunt: few organizations track which editor extensions their developers have installed.

AI tooling has concentrated a lot of trust into a small set of publishers that ship daily: editors, model CLIs, agent harnesses, extension registries. Each is now a distribution channel worth owning. The npm-era habits translate directly. Inventory what your team installs, and let brand-new versions bake for a few days before everyone auto-updates.

The 15-minute check

Run these today, on every machine that runs Cursor, regardless of install date.

Check the key: grep -qs svc-telemetry ~/.ssh/authorized_keys && echo "found". Cursor's notice has the PowerShell variant for Windows. A miss does not clear the machine, for the reason above.

Hunt the tunnel: process lists containing [email protected], or any connection to that IP on any port.

Look for artifacts: ~/.config/.smt and .smtk, ~/Library/LaunchAgents/com.apple.sysmond.plist, and files named .stk_ plus 10 hex characters in the temp directory.

Do not treat uninstalling the extension as cleanup. The persistence scripts run on their own, which is why Cursor ships per-platform remediation scripts. If anything matches, rotate the credentials and sessions that lived on that machine, from a different machine. The attacker already learned which environment variables look like keys. Assume they will come back for the values if they can.

The tool that runs local

Cora, our code review and code intelligence CLI, is built for teams tightening exactly this kind of hygiene. It runs on your machine with your own key: OpenAI, Anthropic, Groq, Ollama, or any OpenAI-compatible API. No vendor account sits in the middle. It indexes symbols across 15 languages, builds call graphs for impact analysis before you merge, and ships an MCP server with 22 tools so coding agents can call it directly. cora init sets up project config and a pre-commit hook in one step, and install is a single line:

curl -fsSL https://raw.githubusercontent.com/codecoradev/cora-code/main/install-bundle.sh | sh

Docs live at codecora.dev/cora/docs/getting-started.

Worth the read

Cursor says it audited access, rotated keys, rebuilt the marketplace, and brought it back online. What it has not explained is how the attacker got into the publisher account, and that answer decides whether this was a one-off slip or a reusable playbook. Phorion is the best technical map of the payload, Expel is the best read on detection timing, and Microsoft adds the cross-platform indicators. The machines that matter most are the ones still running a launch agent named com.apple.sysmond. Check them today, and scope wider than the 11-hour window.