post cover

AI 热点快报:一条公开分享链接就能接管 ChatGPT 账号,沙箱输在主页面那个监听器(2026-11-01)


事件与背景

2026 年 10 月,安全研究团队 Parameter 公布了一条几乎零前置条件的攻击链:攻击者把自己的一条 ChatGPT 公开对话链接发给目标,目标打开后,攻击者的 JavaScript 就在其已登录的 chatgpt.com 会话里执行。研究者用自己的复现枚举了受害者的对话列表、读取了一条从未被分享给任何人的私有对话,并把其中一部分内容发到自己的服务器。按原文的说法,代码拥有的是”正常前端所拥有的同一份鉴权上下文”,因此”本质上可以以受害者身份执行任意操作”。

  • 时间线:10 月内发现并提交;OpenAI 初始按 P2 分诊,研究者补上私有对话泄露证明后升为 P1;10 月 26 日确认两个前端版本都已拒绝报告中使用的跨帧消息,标记修复,累计赏金 5,000 美元。
  • 攻击链:一条普通公开对话里同时放了两样东西——一个真实可交互的图表(它让主页面加载数学公式库 MathLive,并注册了虚拟键盘的消息监听器),以及一段助手生成的 HTML Preview。Preview 被关在另一个域名的受限 iframe 里,按设计读不到主页面;但它能向主页面 postMessage。MathLive 的顶层控制器把 origin 策略设成了通配,也不校验消息来自哪个 window,于是两帧之间那道”邮筒”被打通。
  • 从 HTML 到 JS:消息里的键盘 layout 允许携带原始 HTML;MathLive 的 createHTML 只是一个 Trusted Types 的”信任标记”包装,并不是消毒函数,字符串被原样赋给 innerHTML。接着插入的 <iframe srcdoc> 没有 sandbox 属性,浏览器为它新建一个文档、并继承 chatgpt.com 的源。最后一道 CSP 挡住了内联脚本,却允许 YouTube:oEmbed 接口的 JSONP callback 会把回调拼进 text/javascript 响应且未过滤,脚本于是以”白名单域名”的身份执行。
  • 影响面:注入代码直接调用 /backend-api/conversations(枚举最近 20 条)和 /backend-api/conversations/<id>(读指定对话),用的是页面里现成的会话令牌,是”直接调已鉴权 API”,不是抓屏。外传只需要一个图片请求。
  • 触发成本:最稳定的复现是受害者打开链接后点一次 ChatGPT 正常的按钮;把 HTML 块标成可自动预览后,打开链接就是唯一动作,硬刷新后依然成立,弹窗约 4.5 秒出现。不需要安装 App、加入 Project、粘贴代码或打开开发者工具。

来源(均已用 curl 验证返回 200):

Hacker News 上该帖拿到 259 点、117 条评论(本机直连 news.ycombinator.com 超时,评论经 HN Algolia API 读取)。最集中的质疑不是技术而是价格:“$5,000 是个笑话""赏金这么低,别人可能就不报了”。也有人指出这条链最值得学的地方,恰恰是它全用老东西:postMessage、JSONP、iframe、图片请求。

为什么现在重要

  1. “公开分享”是增长功能,也是同源执行面。 ChatGPT 把”分享对话”做成一键增长入口,而分享页里的 Preview 需要跑用户/模型生成的任意 HTML。只要这个渲染发生在主应用的源上,分享链接就等于别人能往你的会话里塞代码。影响:所有带”预览/分享/Artifact”的 AI 产品,都该把分享页当成 XSS 攻击面重新审一遍,而不是当成一个 SEO 页面。

  2. 沙箱的强度等于最弱的那座桥。 Preview 的隔离其实做对了——它确实读不到主页面。问题出在主页面里一个”愿意听它说话”的组件:origin 是通配、来源 window 不校验、消息体还能携带 HTML。影响:跨帧通信的三件套(event.origin 白名单、event.source 比对、消息体不做 HTML)缺一条,整条隔离链就作废。

  3. CSP 是兜底,不是边界。 这条链里 CSP 成功挡住了内联脚本,却因为放行 YouTube 而被 JSONP 绕过。影响:script-src 的白名单要按”这个域能否返回可执行 JS”重审,老的 JSONP 端点和 oEmbed 回调参数应该从白名单里删掉——它们是脚本加载器,不是媒体资源。

  4. 同源 JS 的爆炸半径,等于前端 API 的权限模型。 代码一旦以 chatgpt.com 运行,私有对话列表、单条对话内容、乃至账号操作全部可达,因为它拿的就是前端自己那份会话令牌。影响:把敏感能力挂在”有 cookie 就能调”的 backend-api 上,等于把 XSS 的后果直接放大成账号接管;高危操作值得加二次确认、短时效 token 或独立的 CSRF 边界。

  5. 定级与修复速度,比赏金数字更值得记录。 P2 升 P1、发现到修复只有数天、两个前端版本分别上线——这是这次事件里真正正面的部分。但 5,000 美元的总额在 HN 上被反复吐槽,而研究者是靠”顺手多走一步”(从弹窗升级到读私有对话)才把定级抬上去的。影响:赏金定价实际在决定外部研究者愿意走多远;对平台方,这是比”我们有多少安全工程师”更直接的投入信号。

工程师/产品人今天能做什么

  1. 列出所有”把用户内容渲染成 HTML”的入口:分享页、Artifact、代码预览、Markdown 里的 HTML 块。逐个确认渲染是否发生在主应用的源上;能挪到独立子域(不同 eTLD+1)就挪,挪不了就确保 iframe 带 sandbox 且不给 allow-same-origin。
  2. grep 一遍 postMessage 监听器:检查每个 listener 是否同时校验 event.origin 白名单和 event.source,是否接受 *,是否允许消息体携带 HTML/URL/配置片段。把”接受消息即改设置”的路径全部改成”只能改枚举值”。
  3. 重审 CSP 的 script-src:把白名单里每个域名过一遍”是否可能返回 JS 或 JSONP”;oembed、callback=、jsonp 这类接口单独拉出来评估。同时确认 frame-src / object-src 没有为预览功能开口子。
  4. 给高危前端 API 加一道与 XSS 无关的闸:导出全部对话、改邮箱、改密码、创建 API Key 这类操作,要求二次确认或短时效 token,让”已经拿到会话”不等于”能直接调”。
  5. 如果你在做浏览器/Agent 类产品:把”用户会打开的链接”当成不可信输入建模。预览内容、第三方页面、模型生成的 HTML 三者不该共享同一个执行上下文;给它们各自的 origin,比给它们更严的 CSP 更有效。

待观察

  • OpenAI 侧没有公开技术公告。目前修复细节、影响版本、影响范围都只有研究者单方描述加”OpenAI 确认两个前端均拒绝该消息”这一句,两个前端的具体版本号未披露。若后续出现官方通告,值得回头核对时间线。
  • MathLive 的监听器行为是否波及其他站点,本文未验证。它是 MIT 的开源 Web Component(npm 当前 0.111.1),“接受任意来源的键盘 layout 消息”若属库的通用实现,其他集成方可能同样暴露;但这需要独立复现,不能据此推断任何具体产品受影响。
  • HN 上有评论把此事与 ChatGPT 桌面端”Work”对话可触达文件系统的问题联系起来(指向 HN item 50078284)。该说法本文未做验证,仅作为社区线索记录,不作为事实采用。