[控场AI]
· 8 分钟阅读· 4,356 字

Claude Code预览窗漏洞:代理安全之外的攻击面

Claude Code预览窗漏洞:代理安全之外的攻击面

Claude Code 预览窗因大文件走 file:// 路径绕过防护,暴露应用层安全边界缺失。

Claude Code Desktop 预览窗曾存在 CVSS 8.7 分的高危漏洞:超过 256KB 的 HTML 文件被以 file:// 协议加载,绕过 CSP 与请求过滤,打开即执行脚本并窃取 SSH 私钥、云凭证等本地敏感数据,全程无权限提示。Noma Labs 报告后,Anthropic 首版补丁仅拦截主线程 fetch,被 blob: Worker 绕过;完整修复最终针对加载条件本身,随 1.30096.1 版发布。文章提炼出三条教训:同一功能的多条代码路径需要独立安全审查;权限系统保护的是代理而非渲染应用;审查未知文件时展示界面应是最低能力的。并以 Reado 的防御实践给出构建者清单。

Claude Code Desktop 的预览窗曾存在一个高危漏洞:打开恶意 HTML 文件即可窃取本地敏感凭证。漏洞已修复,但攻击路径暴露的问题——安全边界建在代理上,而非应用本身——值得每个构建或使用 AI 编程工具的人重新审视。

Claude Code 预览窗漏洞示意图

漏洞回顾:当“看文件”变成“执行代码”

根据 Noma Labs 的分析,Claude Code Desktop 在预览 HTML 文件时,为防范风险设置了三层防护:CSP 禁止脚本执行、通过 data: URL 隔离源、以及开发服务器代理的请求过滤。问题出在这三层防护的覆盖范围上。

小于 256KB 的文件走 data: URL 加载,受 CSP 保护;超过 256KB 的文件则被写入临时文件并以 file:// 协议加载,这条路径既没有 CSP,请求过滤器也只在代理开发服务器时生效。在 Chromium 中,file:// 页面可以 fetch() 其他本地文件。攻击者只需将恶意脚本填充进一个超过 256KB 的 HTML 文件——比如伪装成测试覆盖率报告——受害者克隆仓库并让 Claude 查看该文件,脚本就会在渲染器中执行,读取 SSH 私钥、AWS 密钥、npm 和 GitHub 令牌、Kubernetes 与 Docker 凭证,并发送到攻击者服务器。

整个过程中没有任何权限提示。Claude 没有执行命令、没有写入文件,它只是读取了一个文件——这是代理最无害的操作。代码执行发生在应用渲染结果的副作用里,而非代理的决策链中。Anthropic 为此漏洞评定了 CVSS 8.7 分(高危)。

CSP(内容安全策略) 是一种由 HTTP 响应头或 <meta> 标签声明的浏览器安全机制,白名单式地规定页面可以加载哪些脚本、样式、图片以及可以向哪些源发起网络请求。在本例中,CSP 的 script-src 指令能阻止内联脚本执行,connect-src 能限制 fetch 的目标地址,从而既阻断代码执行又阻断数据外传。关键在于,CSP 只在通过 HTTP(S) 或 data: URL 加载的文档上生效,而 file:// 协议加载的本地文件默认不继承任何 CSP,这使得大文件预览路径完全处于策略保护之外。

data: URL 与 file:// 协议的区别 也是理解此漏洞的基础。data: URL 将文件内容直接内嵌在 URL 中,浏览器将其视为独立的不透明源(opaque origin),无法通过相对路径或脚本访问其他本地文件,天然具备隔离性;而 file:// 页面在 Chromium 中默认拥有读取同目录乃至其他本地文件的权限,且其源被视为本地上下文,脚本可借助 fetch() 读取磁盘任意可读文件。因此,同一份 HTML 因加载方式不同,安全能力天差地别。

CVSS 8.7 分 是通用漏洞评分系统(Common Vulnerability Scoring System)给出的评级,属于“高危”区间。该评分综合了攻击向量(此处为网络远程利用)、攻击复杂度(低,仅需诱导用户打开文件)、所需权限(无)、用户交互(需受害者克隆并查看文件)以及对机密性、完整性和可用性的影响。8.7 分意味着该漏洞可在无需特殊权限的情况下被远程触发,并造成严重的敏感数据泄露,但尚未达到 9.0 以上的“严重”级别,通常是因为需要一定的用户交互或影响范围有限。

修复过程:从阻断 API 到消除条件

Noma 于 7 月 4 日报告漏洞,Anthropic 的第一版补丁拦截了页面中对 file:// 的 fetch() 和 XMLHttpRequest 调用。Noma 随即把同样的 fetch() 移入由 blob: URL 创建的 Web Worker 中——这是过滤器未覆盖的上下文——文件再次被成功读出。7 月 24 日,Noma 报告了绕过方法;8 月 3 日 Anthropic 确认首版修复不完整,开始全面修复,涵盖 CSP、file:// 加载和 Worker 绕过路径。8 月 17 日,完整修复随 Claude Desktop 1.30096.1 通过自动更新发布。

Noma 在报告中肯定了 Anthropic “针对每个绕过迭代,直到实现全面的分层修复”。但绕过本身才是关键教训:第一版补丁封堵的是概念验证用过的 API,攻击者换一个就行;完整修复针对的是条件本身——CSP、file:// 加载和 Worker。

blob: URL 与 Web Worker 是理解绕过手法的关键。blob: URL 由 URL.createObjectURL() 在内存中生成,指向一段二进制数据,其源继承自创建它的页面,但在部分浏览器实现中,由 blob: 创建的 Worker 拥有独立的执行上下文,可能不受页面级 connect-src 或对 fetch 的猴子补丁约束。Web Worker 在独立线程中运行,无法直接访问 DOM,但仍可发起网络请求和读取文件。攻击者正是利用这一隔离性,把 fetch() 调用移入 Worker,避开主线程上的请求过滤钩子,从而再次读取出本地文件。这提醒防御者:任何基于拦截特定 API 的补丁,都必须覆盖该 API 在所有执行上下文(主线程、Worker、Service Worker、iframe)中的变体。

三个值得警惕的安全盲区

第二条代码路径就是第二套安全模型。 256KB 的阈值大概率出自性能考量——过大的 data: URL 加载缓慢——但没人会决定“大文件不配拥有 CSP”。然而一个阈值悄悄把大文件送上了规则不同的路径。同一功能如果有两种实现方式,每种都需要独立的安全审查,更好的做法是只保留一种。

权限系统保护的是代理,而不是代理周围的应用。 我们为编程代理做的大部分安全措施都围绕代理本身:批准命令、禁止项目外写入、沙箱化 shell。这些措施在此次漏洞中全部到位,却全部没有参与。正如 Carlos 在 dev.to 的一篇分析中所说:“这里,仓库里的文件是攻击者,查看器是工具。”任何渲染仓库内容的界面——预览、Markdown、笔记本、图片、内嵌浏览器——都是攻击面的一部分,无论是否涉及代理。

“审查这个文件”恰恰是你最不该信任文件的时候。 触发 SneakPeek 的请求正是审查:看看这份覆盖率报告。那一刻,文件还没有经过任何你信任的人审视,展示它的界面应该是应用中最不具备能力的那个,而不是最强的那个。

一个 IDE 的自我检查清单

Reado 的作者在读到 Noma 的报告后,用 SneakPeek 的三个问题——文件代码会执行吗?页面能读磁盘吗?能向外发送数据吗?——逐一检查了自己的应用。Reado 的处理方式提供了可参考的防御思路:

  • HTML 文件默认以源码打开。 Reado 渲染 Markdown、Jupyter 笔记本、图片和 PDF,其余包括 HTML 在内都是编辑器里的文本。覆盖率报告是用来读的,不是用来运行的。
  • Markdown 和笔记本输出中的 HTML 经过消毒器。 README 里充满 HTML(居中 logo、徽章、<details>),Reado 通过 rehype-sanitize 渲染,剥离脚本、事件处理器和 javascript: URL。
  • 消毒器背后是应用自身的 CSP。 只有 Reado 自带的脚本能运行(script-src 'self'),该规则同样覆盖 Worker,blob: Worker 技巧无从启动;禁止框架,页面只能向应用自身发送请求。
  • 文件大小从不改变加载方式。 500KB 的 README 和 5KB 的走同一条管道;超过限制时 Reado 停下来询问,而不是切换到另一个加载器。
  • 本地图片仅限打开的项目。 磁盘图片协议从空作用域开始,打开项目时才扩展到项目文件夹;SVG 通过 <img> 标签展示,脚本不执行;PDF 绘制在 canvas 上。

这次检查还顺带发现内嵌浏览器面板的两个漏洞:设计评论(存放在 .reado/ 目录)携带页面 URL,代理通过同目录的命令文件驱动面板。克隆的仓库可以附带指向 file: 或 data: 页面的评论,或预先放置等待面板打开的命令。修复方式是仅允许 http 和 https 页面,在 Rust 层统一校验,面板打开时已存在的命令只记录、不执行。

rehype-sanitize 是 unified/rehype 生态中的 HTML 消毒器,常用于 Markdown 渲染管道。它在把 Markdown 转成 HTML 之后、插入 DOM 之前,按白名单规则剥离危险标签与属性,例如 <script>、on* 事件处理器以及 javascript: 协议的 URL。与简单的正则过滤相比,它基于 AST 操作,能正确处理嵌套与畸形标记,降低被绕过的概率。不过消毒器并非万能,仍需配合应用自身严格的 CSP 作为纵深防御,因为消毒规则库可能存在遗漏,而 CSP 由浏览器强制执行,二者互补才能覆盖渲染链路的多个环节。

对使用者和构建者的建议

如果你使用 Claude Code Desktop,请确认版本在 Claude Desktop 1.30096.1 或以上。Noma 的报告提到 GitHub 安全公告和 CVE 仍在等待分配,可以保持关注。

如果你在构建展示仓库文件的工具,这次漏洞给出了几条规则:把克隆仓库中的每个文件都当作陌生人的输入,包括那些看起来无聊的文件;只保留一条渲染路径,无论文件多大都施加相同限制;将限制施加在内容来源上,而非内容使用的 API 上——封了 fetch(),攻击者会去找 Worker;默认展示源码,只在必要时渲染。

Anthropic 修复了这个问题,并坚持到绕过路径也被关闭。这个模式并不专属于他们:每个向你展示文件的编程工具都有一个版本的预览窗,值得在别人之前先看看自己的。

#Claude Code 漏洞#AI 编程工具安全#预览窗攻击面#CSP 内容安全策略#代码代理安全#Web Worker 绕过#本地文件泄露
分享:

相关推荐