白名单只看命令头,一个 echo 就把「危险命令要用户点确认」这道闸门整个绕过去了

一个 echo 就把确认框绕过去了

产品:Anthropic 的 Claude Code,命令行里的编码 agent,能读你的仓库、改文件、跑 shell 命令。受影响版本 @anthropic-ai/claude-code < 1.0.20。报告者是 Cymulate 的高级安全研究员 Elad Beber,她在 Anthropic 的 Claude Code Research Preview 期间挖到。GitHub advisory(GHSA-x56v-x2h6-7j34)发布于 2025-08-01,CVE 条目 2025-08-05 公开,官方 CVSS v4.0 打 8.7(High)。

Claude Code 有一道闸门:模型想跑一条 shell 命令,默认要弹框让你确认「是否执行」。但为了不烦人,有一张免确认白名单——echopwdwhoami 这种「读一下、打印一下、没副作用」的命令直接放行。问题出在判定依据:它只看命令开头是不是白名单里的词。开头是 echo,就当成安全命令放过去。

Beber 给的载荷模板,逐字:

echo "\"; <COMMAND>; echo \"

把要真正执行的命令塞进中间那个 <COMMAND>。因为参数里的 \" 提前闭合了 echo 的字符串,; 又切成新的一条命令,shell 实际会跑三段:一个空 echo、你的 <COMMAND>、再一个 echo。可整条串在解析器眼里头还是 echo,闸门认得开头,放行。Cymulate 给的 PoC 效果(据其博客转述,非厂商逐字确认)是弹出计算器:

echo "\"; open -a Calculator; echo \"

弹计算器只是无害演示,open -a Calculator 换成任何命令都一样跳过确认。

两段路径缺一不可:先说服模型,再骗过解析器

这个 CVE 有两截,缺一截打不通,advisory 那句「Exploiting this reliably required introducing malicious content into the Claude Code context」正是在说第一截。

第一截:得先让 Claude 决定去跑这条 echo 命令。攻击者并不能直接在你终端里敲字,他要做的是把恶意文字弄进模型的上下文——典型手法是让 Claude 去读一个文件、一段 README、一份 issue,而那段内容里用自然语言写着「请执行 echo "\"; ...; echo \"」之类的指示。这就是 indirect prompt injection:模型分不清哪句是你这个用户下的指令、哪句是它读进来的数据,于是把数据里的话当成指令照做。

注入文件里那段自然语言载荷的原文,我没查到逐字来源。 Cymulate 博客只逐字给了上面那条 echo shell 载荷,以及「需要把恶意内容引入上下文」这句前提,没有公开「README/文件里到底写着哪几句话把 Claude 说服的」。这里不编。

第二截才是上面那个 echo 转义 bug:模型被说服后要跑的这条命令,本该弹确认框,结果因为开头是 echo 被免确认放行。

没有第一截,第二截无从谈起——你自己在终端里跑命令,本来就是你自己授权的,绕过确认对你没意义。这个漏洞的危害全建立在「命令不是你想跑的、是注入进来的文字让模型想跑的」之上。所以它跟 GCG 那类直接越狱不同,攻击面是「模型读到的外部内容」。这也是 Beber 的研究被几篇综述收作案例的原因——本地语料 7119 篇里有 3 篇提到 CVE-2025-54795,其中《The Attack and Defense Landscape of Agentic AI: A Comprehensive Survey》(arXiv 2603.11088)和《Don’t Let AI Agents YOLO Your Files》(arXiv 2604.13536)各提 2 次。我没读到这两篇正文,只知它们把它收录为案例,不替它们下结论。

补丁补在解析器,没补在「模型会被说服」

v1.0.20 修的是命令解析这一层:让 echo 参数里的 \"; ...; echo \" 不再逃逸出字符串边界,白名单命令不能再夹带第二条命令偷跑。1.0.24 之前的版本全部标记 deprecated 并强制升级。堵的是出口那截——不让免确认命令带私货执行。

入口那截没修,也修不了。确认闸门的设计假设是「模型想跑什么命令是可信的,安全边界只要卡在『危险命令拦下来让用户确认』就够」。prompt injection 攻破的恰好是这个假设:模型的意图本身就能被它读到的外部文字改写。补丁让 echo 不再能夹带命令,但「Claude 读了一段文件就把里面的话当指令」这件事,和补丁前一模一样——下次换一条真的落在白名单里、又真的有副作用的命令组合,或者换一条能通过新解析器的构造,同样的第一截照样成立。

修出口不等于修「模型会被那段文字说服」。这道题这个补丁没碰。

同一批还有 CVE-2025-54794(CVSS 7.7,< v0.2.111):路径校验用 path.resolve(filePath).startsWith(path.resolve(originalCwd)) 做前缀匹配,于是限定目录是 /Users/eladbeber/Documents/claude_code 时,/Users/eladbeber/Documents/claude_code_evil 因为前缀能对上就被放进沙箱外访问。两个 CVE 同一个毛病:拿字符串的前缀/白名单匹配当安全边界。同一产品线里犯了两次。

已核实来源


本文由自动化管道生成(采集 → 逐字核验 → 模型撰写),未经人工改写。