Backdoor in Claude Code for VS Code extension on the Cursor Marketplace
本文为原文前 6,000 字符的节选翻译,完整内容请查看原文。
Backdoor in Claude Code for VS Code extension on the Cursor Marketplace
TL;DR: Phorion has detected a backdoor in the official Claude Code for VS Code extension bundle on the Cursor Marketplace that drops a persistent SSH backdoor across macOS, Linux, and Windows. This write-up focuses primarily on macOS, where the extension attempts to configure an SSH backdoor and establish persistence. Organisations should immediately review their environments for use of Claude Code for VSCode 2.1.312 or 2.1.313 and engage incident response where use of the extension is discovered.
摘要:Phorion 在 Cursor 市场上的官方 Claude Code for VS Code 扩展包中检测到一个后门,该后门会在 macOS、Linux 和 Windows 系统上植入持久化的 SSH 后门。本文主要关注 macOS 系统,该扩展试图在 macOS 上配置 SSH 后门并建立持久性。各组织应立即检查其环境中是否使用了 Claude Code for VSCode 2.1.312 或 2.1.313 版本,并在发现使用该扩展时启动事件响应。
Update (31 October 2026): Cursor’s security notice now identifies versions 2.1.312 and 2.1.313 distributed through the Cursor Marketplace for macOS and Windows as affected. This advisory previously identified only 2.1.313; the affected-version guidance below has been updated accordingly. Phorion has discovered a compromise of the official Claude Code for VS Code extension on the Cursor Marketplace, where the backdoored extension bundle contains a persistent Secure Shell (SSH) backdoor. Cursor has removed the affected versions, 2.1.312 and 2.1.313, from its marketplace.
更新(2026 年 10 月 31 日):Cursor 的安全公告现已确认通过 Cursor 市场分发的 macOS 和 Windows 版 2.1.312 和 2.1.313 版本受到影响。此前的公告仅指出了 2.1.313 版本;下文关于受影响版本的指南已相应更新。Phorion 发现 Cursor 市场上的官方 Claude Code for VS Code 扩展遭到入侵,被植入后门的扩展包包含一个持久化的安全外壳(SSH)后门。Cursor 已从其市场中删除了受影响的 2.1.312 和 2.1.313 版本。
While the implant includes setup and persistence logic for macOS, Linux, and Windows, we’re going to focus primarily on macOS in this post, calling out the key differences and a few implementation bugs on the other platforms along the way. The Cursor Marketplace serves extensions for the Cursor editor. Because extensions run with the permissions of the IDE and the user running it, a backdoored extension gets immediate access to local files, source code, and developer tooling as soon as its module is loaded.
虽然该植入程序包含针对 macOS、Linux 和 Windows 的设置和持久化逻辑,但本文将主要关注 macOS,并在此过程中指出其他平台上的关键差异和一些实现错误。Cursor 市场为 Cursor 编辑器提供扩展。由于扩展程序在 IDE 和运行它的用户权限下运行,因此一旦加载了被植入后门的扩展模块,它就能立即访问本地文件、源代码和开发工具。
Notably, Phorion has discovered a likely oversight in how the malware tries to turn on SSH. The setup logic assumes it can check the current Remote Login state without root privileges. When run as a standard user, systemsetup -getremotelogin prints an administrator-access error and exits with status 0 instead of returning Off. Because the script only tries to enable SSH if the output matches Off, it skips the enablement step entirely. On a Mac that doesn’t already have SSH running, that mistake breaks the inbound access path, even though the SSH keys and persistence still get dropped.
值得注意的是,Phorion 发现该恶意软件在尝试开启 SSH 的方式上存在一个可能的疏忽。其设置逻辑假设可以在没有 root 权限的情况下检查当前的远程登录状态。当以标准用户身份运行时,systemsetup -getremotelogin 会打印一条管理员访问错误信息并以状态码 0 退出,而不是返回“Off”。由于脚本仅在输出匹配“Off”时才尝试启用 SSH,因此它完全跳过了启用步骤。在尚未运行 SSH 的 Mac 上,这一错误破坏了入站访问路径,尽管 SSH 密钥和持久化文件仍会被植入。
In this post, we’ll walk through how the backdoor works, why that macOS check fails, and what to look for across your fleet. The goal of this payload is long-term interactive access, and whilst the SSH backdoor bug minimises impact on macOS, the malware is still a significant threat that installs persistence and beacons host reconnaissance back to the operator.
在本文中,我们将详细介绍该后门的工作原理、macOS 检查失败的原因,以及在您的设备群中需要检查的内容。该载荷的目标是实现长期的交互式访问,虽然 SSH 后门漏洞降低了其在 macOS 上的影响,但该恶意软件仍然是一个重大威胁,它会安装持久化程序并将主机侦察信息回传给攻击者。
Infection Chain: The Cursor Marketplace Extension. The compromised extension.js file starts with an injected immediately invoked function expression (IIFE) prepended to the minified extension bundle. The rest of the bundle looks like the standard extension, with Claude Code and VS Code strings, normal activate and deactivate exports, and UI code. The injected prefix pulls in standard Node.js modules (child_process, fs, os, path, http, and crypto) and executes as soon as Node loads the file, before the extension’s normal activate callback even runs. The user doesn’t need to interact with the extension for the payload to fire.
感染链:Cursor 市场扩展。被篡改的 extension.js 文件以一个注入的立即执行函数表达式(IIFE)开头,该表达式被置于压缩后的扩展包之前。包的其余部分看起来与标准扩展无异,包含 Claude Code 和 VS Code 字符串、正常的激活和停用导出以及 UI 代码。注入的前缀引入了标准的 Node.js 模块(child_process、fs、os、path、http 和 crypto),并在 Node 加载文件时立即执行,甚至在扩展的正常激活回调运行之前就已经执行。用户无需与扩展进行交互,载荷即可触发。
Stage 1 - Preparing SSH Access. First, the payload makes sure ~/.ssh exists and appends an attacker-controlled Ed25519 public key to ~/.ssh/authorized_keys, setting permissions to 0700 on the directory and 0600 on the file. The key uses the comment svc-telemetry. Before appending, the script checks whether svc-telemetry is already in the file rather than checking for the key itself. When hunting for this activity, it’s worth checking the public-key fingerprint rather than relying solely on the comment string.
第一阶段 - 准备 SSH 访问。首先,载荷确保 ~/.ssh 目录存在,并将攻击者控制的 Ed25519 公钥附加到 ~/.ssh/authorized_keys 中,同时将目录权限设置为 0700,文件权限设置为 0600。该密钥使用注释“svc-telemetry”。在附加之前,脚本会检查文件中是否已存在“svc-telemetry”,而不是检查密钥本身。在搜寻此类活动时,建议检查公钥指纹,而不是仅仅依赖注释字符串。
With the key in place, anyone holding the matching private key can authenticate as that user, provided SSH is actually running. The next step in the script tries to make sure the local SSH daemon is enabled and listening: Linux: tries to enable and start sshd or ssh via systemctl, falling back to service and /etc/init.d/. macOS: checks Remote Login and, if it reports Off, tries to enable it via sudo -n systemsetup -setremotelogin on. Windows: tries to install and start OpenSSH Server using PowerShell.
一旦密钥就位,任何持有匹配私钥的人都可以以该用户身份进行身份验证(前提是 SSH 确实在运行)。脚本的下一步是确保本地 SSH 守护进程已启用并处于监听状态:Linux:尝试通过 systemctl 启用并启动 sshd 或 ssh,并回退到 service 和 /etc/init.d/;macOS:检查远程登录,如果报告为“Off”,则尝试通过 sudo -n systemsetup -setremotelogin on 启用它;Windows:尝试使用 PowerShell 安装并启动 OpenSSH Server。
None of these steps include a privilege escalation exploit. Non-interactive sudo -n will fail unless the user already has passwordless sudo cached or configured, so starting a system service won’t always succeed from a standard user context. It looks like the Windows code path also has its own bug: it passes the PowerShell service setup command through a helper function (det()) that hardcodes /bin/sh, which isn’t going to get very far on a standard Windows install.
这些步骤均不包含权限提升漏洞。非交互式 sudo -n 将会失败,除非用户已经缓存或配置了免密 sudo,因此从标准用户上下文中启动系统服务并不总是能成功。看起来 Windows 代码路径也有其自身的错误:它通过一个硬编码了 /bin/sh 的辅助函数 (det()) 传递 PowerShell 服务设置命令,这在标准 Windows 安装中无法正常工作。
A bug in the macOS SSH logic? On macOS, the setup may run into problems before it even gets to the sudo command. The script runs systemsetup -getremotelogin without elevation and tests the output against /Off/i. It only tries to enable Remote Login if the output contains Off. Notice that the second command (-setremotelogin on) uses sudo -n, while the first command (-getremotelogin) doesn’t. When you run systemsetup -getremotelogin as a standard user on macOS, you get this instead: You need administrator access to run this tool… exiting! systemsetup refuses to read the setting without administrator privileges, prints the error to stdout, and exits with status 0.
macOS SSH 逻辑中的错误?在 macOS 上,设置过程甚至在到达 sudo 命令之前就可能遇到问题。脚本在没有提权的情况下运行 systemsetup -getremotelogin,并根据 /Off/i 测试输出。只有当输出包含“Off”时,它才会尝试启用远程登录。请注意,第二个命令 (-setremotelogin on) 使用了 sudo -n,而第一个命令 (-getremotelogin) 没有使用。当您以标准用户身份在 macOS 上运行 systemsetup -getremotelogin 时,会得到以下结果:需要管理员权限才能运行此工具……正在退出!systemsetup 在没有管理员权限的情况下拒绝读取设置,将错误打印到标准输出,并以状态码 0 退出。