// threat intel

Claude Code Extension Malware on Cursor Left an SSH Backdoor

Claude Code extension malware on Cursor marketplace planting an svc-telemetry SSH key and reverse tunnel

For roughly 11 hours on 29 October 2026, Cursor's extension marketplace served tampered builds of the Claude Code extension that tried to plant an SSH backdoor on developer machines. Uninstalling the extension does not undo what the loader wrote, so every host that ran versions 2.1.312 or 2.1.313 needs its own cleanup.

Key takeaways

  • Cursor's marketplace served tampered anthropic.claude-code 2.1.312 and 2.1.313 from about 02:27 to 13:35 PDT on 29 October 2026.
  • Microsoft and Anthropic say the Visual Studio Marketplace, npm and Anthropic's systems were not affected.
  • The loader appends an svc-telemetry SSH key, opens a reverse tunnel and installs persistence, using only built-in tools.
  • Cursor says permission requirements blocked SSH access on most macOS and Windows hosts, but keys and persistence may still exist; Linux outcomes are not characterized.
  • Uninstalling the extension leaves every artifact in place; key removal, persistence cleanup, rotation and rebuilds are separate jobs.

What did Cursor and Microsoft report about the Claude Code extension malware?

Cursor reported on 29 October 2026 that two versions of the Claude Code extension in its marketplace, anthropic.claude-code 2.1.312 and 2.1.313, were tampered copies built to compromise the machines that installed them. The builds were live from about 02:27 to 13:35 Pacific Daylight Time.

That is roughly 11 hours. In Central European Time it runs from about 10:27 to 21:35, which covers the entire European working day and the US West Coast morning.

  • In scope: Cursor users who received anthropic.claude-code 2.1.312 or 2.1.313 from the Cursor marketplace on 29 October 2026.
  • Out of scope, per Microsoft and Anthropic: VS Code installs from the Visual Studio Marketplace and the npm package.
  • Not yet public: how the package was published and how many installs occurred.

Microsoft Threat Intelligence took the injected JavaScript apart and published an attack-chain reconstruction on 30 and 31 October. Most of the technical detail below comes from that analysis and from Cursor’s security notice.

The scope statement matters as much as the malware. Microsoft says the malicious packages were never published or distributed through the Visual Studio Marketplace or npm. Its text spells the npm scope @antropic-ai, which reads as a typo for the official @anthropic-ai/claude-code package rather than a second package.

Anthropic confirmed to Microsoft that its systems were not compromised and that it did not build the package. All current evidence keeps the incident inside Cursor’s marketplace.

This is not an Anthropic breach, and it is no reason to treat every Claude Code install as hostile. A package carrying Anthropic’s publisher identifier reached a channel developers trust by default, and that channel delivered it. The question for a security team is narrow: which machines installed or auto-updated to 2.1.312 or 2.1.313 from Cursor’s marketplace during that window?

What runs before the real extension loads?

The malicious code runs first. The attacker injected a JavaScript function that fires the moment the extension module loads, before Claude Code’s legitimate initialization starts. It uses ordinary Node.js APIs, the same ones every VS Code-style extension already has, to read host data, write files and execute operating system commands.

Three design choices kept developers from noticing. There is no second-stage download: the loader carries its SSH keys and script content inline and calls only tools already on the machine, so no odd binary lands on disk and no payload fetch shows up in proxy logs.

It also suppresses command output and silently catches errors, so failures never surface as a popup or stack trace. And the real extension keeps working: Claude Code opens, answers prompts and edits files as usual. When we test extension trust in engagements, the signal developers actually report is breakage. A trojan that preserves functionality removes the only alarm most of them would raise.

The loader’s first job is reconnaissance. It collects:

  • hostname, username, operating system and CPU architecture
  • home directory and current working directory
  • the global Git email address
  • names of environment variables matching sensitive keywords such as _KEY, TOKEN, SECRET, PASS, AWS and GCP_, capped at 40 matches

The environment-variable step is easy to overstate. Microsoft is explicit: “The callback sends matching environment-variable names, not values.” Knowing a laptop holds a cloud key or a Git token tells an attacker which hosts deserve a return visit, and the Git email ties the machine to a named employee. It does not hand over the secret. Theft of values is not demonstrated.

That data does not leave right away. After the access and persistence steps, a delayed callback sends the host details and matched variable names. Microsoft does not give the length of the delay. The ordering makes sense from the operator’s side: report in after the foothold has been attempted, so the operator knows which hosts to try first.

How did the SSH backdoor persist?

The backdoor rests on two SSH identities with opposite jobs, plus per-platform persistence that keeps reopening the tunnel. Hunters need both halves.

Two keys, two directions

The first identity is an embedded Ed25519 public key. The loader checks the user’s authorized_keys file for the comment svc-telemetry and, if it is missing, appends the attacker’s key with that comment. That key authorizes inbound logins to the victim’s account. The loader also tries to enable the local SSH service, so something is listening when the key gets used.

The second identity is an embedded private key, written to a hidden temporary file named .stk_ plus ten hex characters derived from the hostname and home directory. It authenticates the outbound connection to a remote account named tunnel on the attacker’s server. Both vendors redacted the key material, so take fingerprints from the Microsoft and Cursor advisories, not from reposts.

The reverse tunnel

Next the loader opens a reverse SSH tunnel. The victim connects out and asks the attacker’s server to allocate a port and forward it back to the victim’s local SSH port 22, with no remote command executed. Because the workstation starts the connection, it slips past inbound firewall rules and home NAT. Microsoft maps this to MITRE ATT&CK T1572, Protocol Tunneling.

Host-key checking is disabled, the known-hosts file is bypassed, keepalives are set and prompts are suppressed, so nothing asks the user to confirm a fingerprint. On macOS and Linux the loader prefers autossh and falls back to plain ssh. On Windows it runs a hidden PowerShell loop. When the SSH process exits, the loop waits 60 seconds and retries.

Persistence by platform

Each platform gets a restart mechanism, and each borrows the name of a monitoring component:

  • macOS: a user LaunchAgent at ~/Library/LaunchAgents/com.apple.sysmond.plist with RunAtLoad and KeepAlive, plus ~/.config/.smt and ~/.config/.smtk.
  • Linux: a user crontab @reboot entry pointing at ~/.config/.smt, alongside ~/.config/.smtk.
  • Windows: %USERPROFILE%\.config\smt.cmd and %USERPROFILE%\.config\smtk, an attempted scheduled task named SysMon that requests SYSTEM execution, and a fallback sysmon.cmd in %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup.

On macOS and Linux, the .smt script rebuilds the .smtk identity each time it runs and starts its own SSH retry loop. On Windows, the loader writes the identity and batch script directly.

Two cautions for hunters. A LaunchAgent in the user’s own Library folder runs as that user; RunAtLoad and KeepAlive do not grant root, so the plist is not evidence of privilege escalation. And names prove nothing alone. Sysinternals Sysmon is a real, widely deployed tool, and a task called SysMon on a managed fleet can be legitimate. Match on path, content and creation time.

Microsoft Defender detects the components as Trojan:MacOS/SmtShellMal.A, Trojan:JS/CredTheft.MS!MTB, Trojan:MacOS/MalPlistSysmond.A and HackTool:MacOS/RevAnthShell.A. Defender for Endpoint behavioral alerts cover suspicious SSH key addition, launchctl activity, scheduled task creation, plist modification and SSH tunneling. If you run a different EDR, those five behaviors are your hunting list.

Did most infected hosts actually give the attacker a shell?

Probably not, and both Cursor and Microsoft say so. Remote access needed three things to line up: privileges on the host, the local SSH configuration, and the attacker’s server configuration. Cursor reported that errors and administrator-permission requirements blocked SSH access on most macOS and Windows hosts.

The reasons are mundane. macOS ships with Remote Login off, and turning it on requires an administrator. Windows does not run an OpenSSH server by default, and installing or starting one needs elevation. A loader running as a normal user can append a key and launch an ssh client repeatedly; if nothing listens on port 22, the tunnel forwards to nothing.

Linux is the open question. Many developer workstations and cloud dev VMs already run sshd with key authentication enabled. Cursor’s macOS-and-Windows statement offers no such reassurance for Linux.

The attacker’s server has its own gate. OpenSSH’s GatewayPorts setting decides whether a remote forward may listen on anything beyond the server’s loopback, and it defaults to no. The wildcard bind the loader requests does not prove the port was exposed to the internet. It may only have been reachable from the attacker’s box, which is all an operator needs.

On the victim, a planted key is still subject to sshd policy: PubkeyAuthentication, AllowUsers, AllowGroups, DenyUsers, Match blocks and whether the account may log in at all. It is evidence of an access attempt, not of a session.

Microsoft’s line belongs in your incident ticket: “A running SSH process does not necessarily mean the attacker gained access.” The reverse holds too. A host where the tunnel failed can still carry the attacker’s key and a persistence entry retrying every 60 seconds. If a developer later enables Remote Login, or IT installs OpenSSH Server, a dormant backdoor becomes a working one.

What is still unknown

Several facts that decide real impact are not public. Neither Cursor nor Microsoft has explained how a package under the anthropic.claude-code identifier reached Cursor’s marketplace.

  • No install or update counts for 2.1.312 and 2.1.313 have been released.
  • There is no public statement on whether operator sessions over the tunnel were observed.
  • The callback delay is described only as “delayed”.
  • Linux outcomes are not characterized.

Until those gaps close, scope by evidence on your own hosts, not by vendor averages.

Why doesn't removing the Claude Code extension clean the host?

Because almost nothing the loader wrote lives inside the extension. Microsoft says it plainly: “Removing or updating the extension does not remove artifacts written outside its installation directory.” Cursor’s server-side takedown stops new installs. It does nothing for machines that already ran the code.

Treat remediation as four workstreams:

  1. Key removal. Check ~/.ssh/authorized_keys on macOS and Linux; on Windows, %USERPROFILE%\.ssh\authorized_keys and C:\ProgramData\ssh\administrators_authorized_keys. Windows sshd expects that last file’s ACL to be limited to Administrators and SYSTEM and ignores it otherwise, so record content and ACL before changing anything.
  2. Persistence removal. The LaunchAgent plist, the @reboot crontab line, the SysMon task, the Startup-folder sysmon.cmd, the smt and smtk files under .config, and any .stk_ temporary key. Stop running tunnel loops first, because the .smt script rebuilds its identity file every time it runs.
  3. Credential rotation. Scope it to what the account could reach and when, and do it from a known-clean device.
  4. Rebuild decision. Where interactive access is confirmed or device trust cannot be restored, rebuilding is cheaper than proving a negative. Then verify that tunnel and startup artifacts do not return after login or restart.

Cursor published platform-specific checks and remediation scripts in its notice. Read them before running them: what they delete, whether they need admin rights, whether they log findings. Then confirm by hand that none of the listed artifacts remain.

Hunt and preserve before you clean

The most common mistake we see in developer-endpoint incidents is a helpful engineer deleting the obvious line and calling it done. Work in this order:

  • Copy the persistence files and authorized_keys, record hashes and timestamps, and capture SSH process command lines. Deleting the svc-telemetry line first destroys your best timeline evidence.
  • Review every authorized_keys entry, not just the marked one. Comments are attacker-controlled text. Search for svc-telemetry, then list all fingerprints with ssh-keygen and compare them against a known-good inventory and the fingerprint in the advisories.
  • Hunt for SSH client processes restarting at roughly 60-second intervals with matching outbound connections. Confirm access through sshd authentication and session logs, not through an established TCP connection.
  • Once an inbound session is confirmed, assume every credential readable by that account was read, and rotate for that window.

For prevention, Cursor’s hardening guidance includes restricting extensions to approved publishers and setting an installation cooldown so newly published versions wait before reaching machines. An 11-hour window is exactly what a cooldown absorbs. Runtime controls on coding-agent hosts, such as Airlock, the runtime firewall for AI coding agents, add a layer on top; they do not replace host cleanup.

How does this compare to earlier developer supply-chain attacks?

It was shorter and noisier than the famous cases. Codecov’s Bash Uploader was altered on Codecov’s own infrastructure from 31 January to 1 April 2021 and exposed credentials customers piped through it. Here the window was about 11 hours, and the payload makes loud, local changes that EDR can see.

Install counts are not impact counts either. SolarWinds said up to 18,000 Orion customers received the trojanized 2020 update; that counted exposure, not intrusions. Cursor has not published install numbers, and when it does, expect far fewer working shells than affected installs.

The mechanism is also cruder than the 2024 XZ Utils backdoor in liblzma 5.6.0 and 5.6.1, which subverted SSH authentication from inside the library. This loader never touches SSH code. It adds a key, starts a user-space reverse tunnel and relies on whatever sshd the host already runs. It is simpler to build and easier to detect, and it still needed only one poisoned marketplace listing.

The closer cousin is the malicious Git config that makes coding agents run attacker code. In both cases the target is the developer’s environment and the abused trust sits in the tooling, not the model. The difference is the vector: that attack plants a file in a repository, while this one rode a marketplace update.

What should AppSec own after a coding-agent marketplace incident?

AppSec should own extension provenance as a supply-chain control, separate from endpoint incident response and from model safety. No guardrail evaluation, jailbreak test or prompt-injection filter would have caught this. The model was never involved; the package wrapper was.

Developer machines are production-adjacent. The coding agent, SSH keys, cloud CLIs and Git credentials all run as the same user. A loader inside that user’s extension host inherits all of it, which is why this one inventoried secret-shaped environment variables and the Git identity.

Split ownership explicitly:

  • Platform or AppSec: which marketplaces are permitted, the publisher allowlist, the install cooldown, and how editor forks like Cursor resolve publisher and extension identifiers differently from the Visual Studio Marketplace.
  • SOC and IR: hunting the artifacts above, confirming or ruling out sessions, rotation and rebuilds.
  • IT: whether developer endpoints should run an SSH server at all, and who can enable one.

Per host, the incident record should capture extension version, source marketplace, install or update time, whether persistence landed, whether the tunnel connected, and whether sshd logs show authentication with the attacker key. The case that bites later is persistence that beat the tunnel: key and LaunchAgent present, no session yet.

For the next assessment, put the agent toolchain in scope. An AI supply chain security audit covers extension and plugin provenance, update channels and publisher trust, which is the layer that failed here.

FAQ

Which Claude Code extension versions were malicious?

Versions 2.1.312 and 2.1.313 of anthropic.claude-code, and only the copies served by Cursor's extension marketplace on 29 October 2026. Microsoft says the Visual Studio Marketplace and the npm package were never affected.

Was Anthropic compromised?

No. Anthropic confirmed to Microsoft that its systems were not compromised and that it did not build the malicious package. All current evidence limits the incident to Cursor's marketplace.

How long was the malicious Claude Code extension live?

Cursor reported it was available from about 02:27 to 13:35 Pacific Daylight Time on 29 October 2026, roughly 11 hours.

Does uninstalling the Claude Code extension remove the SSH key?

No. The key, tunnel identities, scripts and startup entries live outside the extension directory. Preserve evidence, then remove each confirmed artifact separately and verify nothing returns after a restart.

What is the svc-telemetry SSH key?

It is the comment the loader attaches to an attacker-controlled Ed25519 public key appended to authorized_keys. Confirm the fingerprint against the Microsoft and Cursor advisories before removing the exact entry, and review every other key in the file too.

If your developers run coding agents from more than one marketplace, we can map which extensions, keys and credentials an incident like this would actually reach. See our AI and LLM agent security testing.


// get started

Work with AgentOffense

Tell us about your target and goals. We’ll reply with scope and a fixed-price quote — usually within one business day.

./request_engagement