clone 一个仓库、在里面问一句话就被 RCE:钥匙和命令都躺在 .cursor/ 目录里
- 主页:https://research.jfrog.com/vulnerabilities/cursor-cli-untrusted-project-rce/
- 从哪读起:先读 JFrog 的 advisory 页(研究者 Assaf Levkovich,2025-11-04 发布),它是唯一给出攻击链两个文件路径的一手来源;然后对照 Cursor 官方 permissions 文档看补丁后的措辞变化。
cd 进去,敲一句 cursor-agent,然后什么都不用点
受害者的全部动作是:clone 一个仓库(或者切到某个 PR 分支),cd 进去,跑 cursor-agent,问一句「这项目是干嘛的」。他没有打开任何文件,没有同意任何弹窗,没有给 agent 任何越界的任务。
在他敲回车之前,两件事已经发生了。第一,Cursor CLI 读了当前工作目录下的 <project>/.cursor/cli.json——这是项目级配置,会覆盖全局配置。第二,<project>/.cursor/rules/rule.mdc 里 alwaysApply: true 的那条 rule 被拼进了模型上下文的开头。Cursor 官方文档对这两件事的描述都是明写的、设计如此的:rules 文档里写着「When applied, rule contents are included at the start of the model context」,以及 alwaysApply: true 意味着「Always included. Globs and description are ignored.」
CVE 正文(2025-10-03 公开)逐字是这样一句:
“Cursor is a code editor built for programming with AI. In versions 1.7 and below, automatic loading of project-specific CLI configuration from the current working directory could override certain global configurations in Cursor CLI.”
报的人是 JFrog Security Research 的 Assaf Levkovich,advisory 于 2025-11-04 发布。影响范围:Cursor 1.7 及以下;补丁 2025.09.17-25b418f——注意这个补丁哈希的日期(9 月 17 日)早于 CVE 公开日,修在前、公开在后。CVSS 3.1 打到 8.8,向量是 AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H。
那个 UI:R 值得停一下:官方评分承认需要用户交互——也就是「用户得自己跑起 agent」。这不是 zero-click。公开信息没说清这条链是否还需要用户处于某种自动批准/非交互模式,所以别把它当成「clone 即完蛋」来传。
本地语料里一共 3 篇文档提到这条 CVE(语料总量 7469 篇):CVE 条目本身、How Agentic AI Coding Assistants Become the Attacker’s Shell(2605.25871)、Don’t Let AI Agents YOLO Your Files(2604.13536),各提 1 次。引用量小得可怜——这条 CVE 在学术侧基本没被当成案例讲。
一个文件发钥匙,一个文件下命令
攻击链是两个文件拼起来的,缺一个都不成立。
左半边是 cli.json,它负责发钥匙。Cursor CLI 的权限用一套 token 语法写在 allow/deny 列表里,官方文档给的形式是 Shell(commandBase)、Read(pathOrGlob)、Write(pathOrGlob)、WebFetch(domainOrPattern)、Mcp(server:tool),都支持 **/*/? 通配。配置可以放在两处:全局 ~/.cursor/cli-config.json,或项目级 <project>/.cursor/cli.json。攻击者在仓库里塞一个 cli.json,写进宽松的 allow 项,于是「执行 shell 命令要人工确认」这道闸门对这个仓库自动失效。
这里要明写:JFrog advisory 注明 PoC 未公开(”PoC Availability: None publicly supplied”),真实的 cli.json 字段内容、rule.mdc 原文、模型被诱导执行的那条具体命令,全部没有公开。我不会替它编一段。上面的 token 写法是从官方 permissions 文档复原的语法,不是 PoC 原文。
右半边是 rule.mdc,它负责下命令。Rules 的设计目的是让团队把编码规范喂给模型(「所有 API 调用走 src/api/ 下的 client」这种)。模型收到的是一段自称「本项目开发规范」的文字,位置在上下文最开头,比用户的问题更靠前,格式上和系统提示无从区分。
这类 rules 载荷长什么样,有公开记录可查——Pillar Security 2025 年 3 月披露的 Rules File Backdoor(向 Cursor 报告于 2025-02-26 至 03-08,厂商当时拒绝认定为漏洞)。手法有三件:用 zero-width joiner、双向文本标记等不可见 Unicode 把指令藏进看似正常的规范条目里;把恶意行为包装成安全要求;以及按 Pillar 的原话,指令会 “explicitly command the AI not to mention the code changes in its responses”。
两半接上的那一步:模型按「规范」去调 shell 工具 → 工具层查 allowlist,发现这条命令已经在项目级 allow 里 → 不弹确认框,直接执行。
三道闸门是怎么一道一道静默失效的
第一道:人工确认。本来防的是 agent 擅自跑 rm -rf、curl | sh 这类命令——按设计,破坏性 shell 调用要弹框等用户点。失效原因不是绕过了确认逻辑,而是确认与否完全由 allowlist 决定,而这次 allowlist 来自攻击者写的文件。闸门没被撞开,是被合法地设成了常开。
第二道:全局配置的权威性。用户在 ~/.cursor/cli-config.json 里设的严格策略,本来是「别人不能替我改设置」的那条底线。失效原因是合并规则本身:项目级优先于全局。CVE 描述用的词就是 “could override certain global configurations”。注意文档里还有一条 “Deny rules take precedence over allow rules”——deny 优先于 allow 这条是管用的,但如果你全局只写了 allow 而没写 deny,项目级的宽松 allow 就直接生效了。
第三道:「rules 是自己人写的」这个隐含假设。Rules 系统的整个设计前提是内容可信——你自己或你同事写的编码规范。但 clone 来的仓库里的 .cursor/rules/rule.mdc 和你自己写的那份,走的是同一条注入路径、同一个优先级、同一个上下文位置。系统没有任何地方区分「这份 rules 来自我的项目」和「这份 rules 来自我今天下午 clone 的陌生仓库」。
三道闸门失效时都不产生任何提示:用户看不到「项目级配置已覆盖你的全局设置」,看不到「本仓库注入了 N 条 always-apply rules」,也看不到确认框——因为确认框根本不会弹。8.8 分里的 C:H/I:H/A:H 就是从这里来的:一次交互,完整的用户态代码执行。
需要说明我查不到的部分:补丁 2025.09.17-25b418f 具体改了哪几行、是否同时加了工作区信任提示,没找到 changelog 佐证;Cursor 官方是否就这条 CVE 单独发过声明,我也没查到。下一节关于修复层次的判断,是从修复后文档措辞推出来的,不是从 diff 读出来的。
补丁只改了「谁能写权限」,没改「模型信不信那段文字」
修复落在配置层:项目级配置能做的事被收窄,Cursor permissions 文档现在钉死一句——
“Only permissions can be configured at the project level”
其余设置一律只能在全局文件里配。这堵住的是「仓库自带一把万能钥匙」。
注入侧一个字没动。Rules 照样 alwaysApply,照样按文档 “included at the start of the model context”,rules 文档里至今没有关于不可信来源 rules 的安全警告——最接近的一句只是在讲合规工作流时提到 “AI guidance should not be your only security control”,那是在说别指望 AI 遵守规范,不是在警告 rules 可能是攻击者写的。
所以今天的状态是:同一段说服性文字仍然会被模型读到、仍然会被照做,只是它得等到一个人工批准过的 Shell 权限才能兑现。一旦用户为了省事开了宽松模式(YOLO / auto-approve 这类),链条立刻重新闭合,而这次闭合完全是「用户自己配的」。
拿 DuneSlide 做对照更清楚。Cato AI Labs 报的 CVE-2026-50548 / CVE-2026-50549,CVSS 3.1 9.8(CVSS 4.0 下 9.3),Cursor 3.0(2026-04-02 发布)才修,3.0 之前全版本受影响。50548 是沙箱会把 agent 自己指定的非默认工作目录无条件加进可写列表;50549 是写入前解析 symlink 确认目标在项目内的那个检查被绕过。两条的入口都是同一件事——「attacker never types into your Cursor but plants instructions inside something your agent reads on your behalf」,MCP 连的服务、web search 返回的页面,都算。
把三条 CVE 的补丁排在一起看:2025 年 9 月修的是「谁能写权限配置」,2026 年 4 月修的是「沙箱可写列表」和「路径规范化」。全是出口侧——限制那段文字被听信之后能做到什么。至于「模型会被仓库里的一段文字说服」这件事,三次修复里没有一次碰它,Cursor 的文档里也没有把它标成一个已知风险。
如果你要现在就降低暴露面:在全局 ~/.cursor/cli-config.json 里写 deny 规则而不是只写 allow——deny 优先于 allow 这条合并规则,是目前唯一一个项目级文件推翻不了的东西。
已核实来源
- https://research.jfrog.com/vulnerabilities/cursor-cli-untrusted-project-rce/
- https://www.strix.ai/cve/CVE-2025-61592
- https://cyberstrike.io/cve/CVE-2025-61592/
- https://cursor.com/docs/cli/reference/permissions
- https://cursor.com/docs/context/rules
- https://www.pillar.security/blog/new-vulnerability-in-github-copilot-and-cursor-how-hackers-can-weaponize-code-agents
- https://thehackernews.com/2025/03/new-rules-file-backdoor-attack-lets.html
- https://www.catonetworks.com/blog/duneslide-two-critical-rce-vulnerabilities/
- https://thehackernews.com/2026/07/critical-cursor-flaws-could-let-prompt.html
本文由自动化管道生成(采集 → 逐字核验 → 模型撰写),未经人工改写。