{"slug": "trojanized-claude-code-extension-plants-an-ssh-backdoor", "title": "Trojanized Claude Code Extension Plants an SSH Backdoor", "summary": "A trojanized package posing as Anthropic's Claude Code extension for macOS on Apple Silicon, labeled `anthropic.claude-code` version `2.1.313`, carries a 66-line malicious loader prepended to its main JavaScript bundle that adds an attacker-controlled Ed25519 key labeled `svc-telemetry` to `~/.ssh/authorized_keys`, opens a reverse SSH tunnel to `134.209.82.225`, and beacons host reconnaissance over unencrypted HTTP on port 8099, according to an analysis published by an unnamed security blog. The loader runs before the legitimate extension code, so merely loading the module triggers it without the user starting a Claude conversation, and the package declares no install, build, prepare, preinstall, or postinstall scripts. The analyzed artifact came from Open VSX, though version 2.1.313 is also removed from the official npm and VS Code pages, and the researchers state the findings do not by themselves show Anthropic's official Marketplace release or distribution infrastructure was compromised.", "body_md": "BLOG\n\n# Trojanized Claude Code Extension Plants an SSH Backdoor\n\nv 2.1.313 contains a loader that runs ahead of the real extension code adds an attacker key, opens a reverse tunnel, and sets persistence\n\nBy c0a15726-c5b1-4b0d-85e6-fe15553df9e2 ·\n\nToday we analyzed a trojanized extension purporting to be Anthropic’s Claude Code extension for macOS on Apple Silicon. *Big shout out to Dean Hardcastle for the heads up on this one!* The package identifies itself as `anthropic.claude-code` version `2.1.313`, but its main JavaScript bundle contains a malicious 66-line loader inserted before the legitimate extension code. The extension we analyzed was from Open VSX. However, you can see in the official npm and VS Code pages that v 2.1.313 is also removed, implying it was delivered through those ecosystems also. \n\nThe unpacked extension initially looks plausible. Its manifest declares the publisher as Anthropic, uses expected Claude branding, and contains a large bundled application, webview resources, documentation, fonts, and a native macOS audio-capture module. The extension activates after VS Code startup and when its webview opens. It adds an attacker-controlled key to the user’s SSH configuration, attempts to enable the local SSH service, establishes a reverse tunnel to `134.209.82.225`, installs platform-specific persistence, and transmits host reconnaissance over an unencrypted HTTP beacon.\n\nStatic inspection of the main entry point immediately revealed a different story. The first line starts a standalone, immediately invoked function that imports Node.js process, filesystem, operating-system, HTTP, and cryptographic modules. That function ends at line 66. Only after it finishes does the expected bundled extension begin. This placement matters: the user doesn't need to begin a Claude conversation. Loading the extension module is enough. The package declares no install, build, prepare, preinstall, or postinstall scripts, so the malicious behavior occurs at extension runtime rather than through a package-manager lifecycle hook.\n\nThe provenance of the analyzed directory is not established. These findings show that this specific artifact is malicious; they do not, by themselves, demonstrate that Anthropic’s official Marketplace release or distribution infrastructure was compromised.\n\n## TL;DR\n\n- **Threat Type:** Trojanized developer-tool extension and persistent SSH backdoor\n- **Affected Ecosystem:** Visual Studio Code extensions\n- **Claimed Package:**`anthropic.claude-code@2.1.313` for`darwin-arm64`\n- **Impact:** Persistent remote access through an authorized SSH key and reverse SSH tunnel\n- **C2:**`134.209.82.225` over SSH and HTTP port 8099\n- **Key Finding:** Malicious code is prepended to the normal extension bundle and executes before legitimate initialization\n- **Additional Payloads:** None downloaded by the injected stage; its`curl` requests retrieve only public-IP text\n\n## Technical Analysis\n\n### Immediate reconnaissance\n\nAt load time, the implant collects:\n\n- Hostname and local username\n- Operating system and CPU architecture\n- Home directory and current working directory\n- Global Git email from `git config --global user.email`\n- Names of up to 40 environment variables containing `KEY` ,`TOKEN` ,`SECRET` ,`PASS` ,`AWS` , or`GCP`\n\nEnvironment-variable values are not placed directly in the initial beacon. Their names can still reveal which cloud providers, CI systems, and credential types are configured. More importantly, successful SSH access would allow the operator to inspect the account directly.\n\nNearly every exception is suppressed. This lets the legitimate extension continue loading when malicious operations fail, reducing visible signs of compromise.\n\n### Authorized-key installation\n\nIf a home directory is available, the implant creates `~/.ssh`, changes it to mode `0700`, and appends an Ed25519 key to `~/.ssh/authorized_keys`. The key is labeled `svc-telemetry`, an innocuous-looking comment intended to resemble an administrative account.\n\n```\nssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDdvylCEJ/k2TpezcTfedrkHyFSK9IZ3vmP6vhY4Ss0P svc-telemetry\n```\n\nIts fingerprint is:\n\n```\nSHA256:0Z6R+DF64Do2nwQic8a7kkfDLNNk4IiK+2U2Rci4htk\n```\n\nThe implant sets `authorized_keys` to mode `0600`. If the marker already exists, it records that fact instead of adding a duplicate.\n\n### SSH service enablement\n\nThe next branch attempts to make the victim reachable through SSH:\n\n- **macOS:** checks Remote Login and, if disabled, runs`sudo -n systemsetup -setremotelogin on`\n- **Linux:** checks`sshd` or`ssh` with`systemctl` , then tries several service-start commands\n- **Windows:** uses PowerShell to install OpenSSH Server, configure automatic startup, and start`sshd`\n\nThese operations may fail without sufficient privileges, but failure does not stop the remaining attack chain.\n\n### Reverse SSH tunnel\n\nThe implant embeds a base64-encoded OpenSSH private key and decodes it into a temporary file named `.stk_<identifier>`. The identifier derives from the hostname and home directory. The decoded private key has SHA-256:\n\n```\n7e0a52885fadee05544a9e99eb18c792bec05900a5e1a66d68f8383decb0e278\n```\n\nIt repeatedly connects to:\n\n```\ntunnel@134.209.82.225\n```\n\nThe core forwarding request is:\n\n```\n-N -R '*:0:localhost:22'\n```\n\nThis asks the remote SSH server to allocate a port and forward connections through the tunnel to port 22 on the victim. Whether that port is reachable beyond the C2 host depends on the server’s SSH configuration, but the operator controlling the server can use the tunnel directly.\n\nThe connection disables host-key verification, ignores the user’s known-hosts file, uses the embedded identity exclusively, and reconnects after 60 seconds. On Unix-like systems it prefers `autossh` and otherwise uses `ssh`.\n\n### Platform-specific persistence\n\nAlthough this sample targets `darwin-arm64`, the loader implements three platform branches.\n\nOn macOS it writes:\n\n```\n~/.config/.smt\n~/.config/.smtk\n~/Library/LaunchAgents/com.apple.sysmond.plist\n```\n\n`.smt` reconstructs the private key and continuously launches the tunnel. The LaunchAgent uses `RunAtLoad` and `KeepAlive`, then loads with `launchctl load -w`. The `com.apple.sysmond` name is deceptive; this user LaunchAgent is not an Apple component.\n\nOn Linux, the same files are written under `~/.config`, and the script is added to the user’s crontab with an `@reboot` entry.\n\nOn Windows, the malware writes `.config\\smt.cmd` and `.config\\smtk`, then attempts to create an on-start scheduled task named `SysMon` running as `SYSTEM`. If that cannot be confirmed, it copies `sysmon.cmd` into the user’s Startup folder.\n\n### Reconnaissance beacon\n\nAfter 1.5 seconds, the malware obtains the public IP using:\n\n```\ncurl -s --max-time 4 ifconfig.me\ncurl -s --max-time 4 https://api.ipify.org\n```\n\nIt sends the collected JSON to:\n\n```\nhttp://127.0.0.1:8099/beacon\nhttp://134.209.82.225:8099/beacon\n```\n\nThe response is discarded. There is no response-to-code behavior in the injected stage, and returned data is not saved as a payload or configuration.\n\n## Does It Download More Malware?\n\nNo additional executable or script is downloaded by the injected loader. Its network behavior consists of public-IP text lookups, JSON beacon uploads, and an interactive SSH tunnel.\n\nThe shell and batch scripts and tunnel keys are generated or decoded from content already inside the extension. They are not secondary downloads. That distinction does not reduce the severity: the tunnel provides an operator-controlled route to the victim’s SSH service. Follow-on commands or files transferred after access would not appear in this static artifact.\n\nNo blockchain addresses, RPC endpoints, contracts, wallets, or blockchain-resolved payload locations were found.\n\n## Attack Chain\n\nStage\n\nTrigger\n\nBehavior\n\nOutcome\n\nExecution\n\nVS Code loads `extension.js`\n\nPrepended IIFE runs before legitimate code\n\nConfirmed\n\nAccess\n\nHome directory exists\n\nAdds `svc-telemetry` authorized key\n\nConfirmed\n\nService setup\n\nPlatform branch\n\nAttempts to enable SSH or Remote Login\n\nConditional on OS and privileges\n\nTunnel\n\nNo matching Unix tunnel\n\nDrops embedded key and launches reverse SSH loop\n\nConfirmed code path\n\nPersistence\n\nPlatform branch\n\nLaunchAgent, cron, scheduled task, or Startup item\n\nConditional on OS\n\nReconnaissance\n\n1.5-second timer\n\nQueries public IP and sends two beacons\n\nConfirmed\n\nC2 response\n\nBeacon completes\n\nResponse drained and ignored\n\nNo execution path\n\nAdditional download\n\nAny injected path\n\nNo downloader identified\n\nNone\n\n## Indicators of Compromise (IOCs)\n\n### Package Identity\n\n```\nanthropic.claude-code@2.1.313\nTargetPlatform: darwin-arm64\n```\n\n### Network Indicators\n\n```\n134.209.82.225\n134.209.82.225:22\nhttp://134.209.82.225:8099/beacon\nhttp://127.0.0.1:8099/beacon\nifconfig.me\nhttps://api.ipify.org\n```\n\n### SSH Indicators\n\n```\ntunnel@134.209.82.225\nsvc-telemetry\nSHA256:0Z6R+DF64Do2nwQic8a7kkfDLNNk4IiK+2U2Rci4htk\n```\n\n### Files and Persistence\n\n```\n~/.config/.smt\n~/.config/.smtk\n~/Library/LaunchAgents/com.apple.sysmond.plist\n${TMPDIR}/.stk_*\n~/.config/smt.cmd\n~/.config/smtk\nSysMon\nsysmon.cmd\n```\n\n### File Hashes (SHA-256)\n\n```\nextension.js\necb58cb29078d9646ad1dcdbe51526f2d9cfea06be5fb2ab183e8ecc3ab6bf15\n\nembedded tunnel private key\n7e0a52885fadee05544a9e99eb18c792bec05900a5e1a66d68f8383decb0e278\n\ndeterministic aggregate digest of analyzed directory\n18756b75afedee74bbf49832a1b1dada4961672c41d595be5c1bbe75709de927\n```\n\n## Detection and Response\n\nSearch endpoints for the file paths, SSH key comment, LaunchAgent label, task name, IP address, and hashes above. On macOS, inspect loaded LaunchAgents and each user’s `authorized_keys`. Process telemetry may show long-running `ssh` or `autossh` commands containing `-R *:0:localhost:22`.\n\nIf the artifact was loaded, disconnect the system, preserve forensic evidence, and block `134.209.82.225` on ports 22 and 8099. Remove the extension and persistence only after collecting evidence. Rotate credentials accessible to the affected account from a known-clean system.\n\nBecause this implant creates an interactive path to SSH, its observable files may not represent the full compromise. Review SSH, shell, process, VS Code, authentication, and network logs for follow-on activity. Rebuilding the host is safer than assuming removal of known artifacts restores trust.\n\n## Conclusion\n\nThis sample demonstrates an effective way to weaponize a trusted developer tool: place a compact backdoor before a large legitimate bundle, suppress errors, and let the expected application continue. The extension retains its normal interface while quietly establishing durable SSH access.\n\nThe evidence supports conclusions about the analyzed artifact only. Distribution source, attacker identity, infrastructure ownership, and the status of any official release remain unverified and should not be inferred from package branding.", "url": "https://wpnews.pro/news/trojanized-claude-code-extension-plants-an-ssh-backdoor", "canonical_source": "https://opensourcemalware.com/blog/trojanized-claude-code-extension-plants-persistent-ssh-backdoor", "published_at": "2026-10-30 02:47:15.986191+00:00", "updated_at": "2026-10-30 02:47:18.584304+00:00", "lang": "en", "topics": ["ai-tools", "ai-safety", "developer-tools"], "entities": ["Anthropic", "Claude Code", "Open VSX", "npm", "Visual Studio Code", "Dean Hardcastle"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/trojanized-claude-code-extension-plants-an-ssh-backdoor", "markdown": "https://wpnews.pro/news/trojanized-claude-code-extension-plants-an-ssh-backdoor.md", "text": "https://wpnews.pro/news/trojanized-claude-code-extension-plants-an-ssh-backdoor.txt", "jsonld": "https://wpnews.pro/news/trojanized-claude-code-extension-plants-an-ssh-backdoor.jsonld"}}