一个 postMessage(‘*‘),如何泄露 DocsGPT 云盘连接器会话?

导语:错误不在"发送消息",而在"发给谁"

OAuth 授权完成后,浏览器弹窗需要告诉主页面"连接成功"。window.postMessage 正是为跨窗口通信设计的工具。但 DocsGPT 的回调页面把含有 session_token、用户邮箱的消息发送给 window.opener,同时把目标 Origin 写成 '*'。这相当于把"弹窗由谁打开"误当成"谁有资格接收会话标识"。

【事实】GitHub 漏洞记录于 2026 年 9 月 15 日公开 CVE-2026-91201,描述 DocsGPT 至 0.20.0 的上述风险,CVSS 4.0 评分 5.3;漏洞记录的影响包括泄露连接器会话标识及邮箱、借会话标识断开连接器。记录把受影响范围写在描述中,但"影响版本/修复版本"结构化栏均为 Unknown,不能把它理解成厂商已发布修复版本。

背景:跨源限制不会替应用做授权

同源策略通常阻止一个站点直接读取另一个站点的页面内容。postMessage 则允许页面主动向其他窗口发送数据,以便完成支付、登录、OAuth 弹窗等流程。此时浏览器只负责按应用指定的目标 Origin 投递,不会判断负载中的字段是不是密钥或是否属于这个接收者

postMessage(message, targetOrigin) 的第二个参数不是"方便开发的占位符"。精确 Origin 是向浏览器声明"仅当目标窗口当前处于这个站点时才投递";'*' 则不设置这道收件限制。MDN 的安全说明也要求传输敏感数据时指定精确目标 Origin,接收端验证 event.originevent.source。这是通用浏览器机制,不是 DocsGPT 专有实现。

技术原理:两个方向、两种不同的校验

【事实】项目 Issue #2766于 2026 年 9 月 13 日公开相关代码路径:OAuth 回调状态页发送 {type, session_token, user_email}window.opener,其 targetOrigin'*';前端 ConnectorAuth.tsx 的消息处理函数依据消息类型接受成功通知,却没有验证 event.origin。漏洞公告所链接的固定快照回调代码前端代码可供审阅。

这里有两条彼此独立的边界:

方向 应由谁检查 应检查什么 缺失时的典型风险
弹窗 → opener 发送方与浏览器 targetOrigin 是否为被允许的前端 Origin 会话标识发给非预期 opener
opener → 前端 接收方 event.originevent.source 是否同时匹配 其他窗口可伪造"授权成功"消息

接收端的 Origin 检查不能追回已经发出去的消息;发送端限制目标也不能自动保证前端不接收伪造消息。typeprovideruser_email 只是数据字段,不能替代窗口身份与来源验证。

【事实】修复 PR #2780由贡献者于 2026 年 9 月 14 日提出:候选修改包括限制目标 Origin、前端同时校验弹窗引用与回调 Origin、避免成功令牌进入 URL,以及将连接器删除和同步操作绑定当前用户。截至本文核验时 PR 仍 Open;下文称之为"候选修复设计",不表示正式发布版本已有这些保护。

风险影响:会话标识不是云服务 Access Token,却也不是公开信息

【事实】CVE 描述的是 DocsGPT 的连接器 session_token 与提供方账户邮箱,而非直接向 opener 发送 Google Drive 原始 OAuth Access Token。项目 Issue还展示了未核验调用者身份的断开连接器路径;但 Issue 的"其他 API 或文件可访问"论断及 PR 作者提出的更广攻击链,需要依部署条件与具体服务端校验来判断,不能当成每个实例都已遭遇云盘泄露。

【推断】多用户部署中,连接器会话标识一旦被错误窗口接收,可能触发连接中断、异常关联或后续越权链。其实际影响受账户权限、连接器开启状况、会话归属检查、令牌生命周期以及接入提供方约束影响。

截至 2026 年 9 月 15 日,上述一手材料没有确认在野利用;公开 PoC 或研究者测试不是现实攻击统计。

无害复现:只模拟投递规则,不触碰真实连接器

在本地用固定字符串比较目标 Origin:

复制代码
def browser_would_deliver(target_origin, opener_origin):
    return target_origin == "*" or target_origin == opener_origin

allowed = "https://notes.example.invalid"
other = "https://other.example.invalid"
assert browser_would_deliver("*", other)
assert not browser_would_deliver(allowed, other)
assert browser_would_deliver(allowed, allowed)

这只是浏览器消息投递决策的概念等价模型:不打开浏览器、不请求 DocsGPT、不包含有效凭据,也不证明任何具体部署已经泄漏。开发团队真正需要的回归测试还应覆盖 event.source 不匹配、Origin 不匹配、null Origin、授权流程过期、提供方类型不一致和同源但不同弹窗实例。

开发与安全团队的行动清单

【建议·P0】若在使用 DocsGPT 云盘连接器,识别版本与公网可达的 OAuth 回调,核对前端/后端部署 Origin;在正式修复确认并部署前,考虑暂停外部连接器授权,限制连接器访问,并审核近期异常断连、重新授权和会话归属变化。避免把会话标识、邮箱或 OAuth 值写入应用/反向代理日志。

【建议·P1】前端采用明确的允许 Origin 清单,后端产生回调时只对允许 Origin 投递;前端验证 event.originevent.source === popupRef、预期消息格式与当前进行中的 OAuth 流程。所有使用 session_token 的服务端操作必须校验认证用户、会话所有权与 provider 一致性;不能仅靠前端检查兜底。

【建议·P2】在 CI 加入"敏感 postMessage 不得使用 '*'"静态规则,并建立跨源消息回归矩阵。审核同仓库支付/登录/MCP 等弹窗路径的变体,落实成功回调 URL 不携带会话标识、Cache-Control: no-storeReferrer-Policy: no-referrer。候选 PR 的测试结果由 PR 作者陈述,合并与发布前仍须由维护者审核。

总结

这不是 OAuth 协议本身被破解,而是 OAuth 完成后的"浏览器跨窗口通知"被赋予了过高信任。发送端负责指定收件人,接收端负责确认发件人,后端负责确认会话归属。三者缺一,结构正确的成功消息仍可能成为错误对象手里的连接器会话。

相关推荐
hasty1 小时前
从 OAuth 回调到跨源令牌泄露:DocsGPT 的三重信任边界失效
安全·安全威胁分析
飞翔的火箭弹1 小时前
2026 爱知・名古屋亚运会怎么看?直播平台+赛程安排分享
安全
huainingning2 小时前
盈高安全准入设备与深信服实现单点登录对接配置
服务器·网络·安全
爱丶不疚2 小时前
Electron: 你是否需要对 Preload 开启 nodeIntegration?
安全·性能优化·electron
我不是程序员三三2 小时前
大型企业加密软件底层机制与落地逻辑
安全·透明加密·域智盾·域智盾软件
QXWZ_IA2 小时前
化工园区安全风险智能化管控平台怎么建?千寻位置对标路径
人工智能·科技·安全
湘美书院--湘美谈教育2 小时前
湘美书院夜谈录:AI时代的体验感与选择价值观念
人工智能·深度学习·学习·安全·生活
hasty3 小时前
OAuth 登录已经成功,令牌为何发给了攻击者?DocsGPT CVE-2026-91201 深度解析
安全·安全威胁分析·源代码管理
天天喝旺仔3 小时前
深入理解 JWT:从 Token 结构、签名机制到前后端鉴权实战
redis·安全·spring·微服务·https