一个 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.origin 与 event.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.origin 与 event.source 是否同时匹配 其他窗口可伪造"授权成功"消息

接收端的 Origin 检查不能追回已经发出去的消息;发送端限制目标也不能自动保证前端不接收伪造消息。type、provider、user_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.origin、event.source === popupRef、预期消息格式与当前进行中的 OAuth 流程。所有使用 session_token 的服务端操作必须校验认证用户、会话所有权与 provider 一致性;不能仅靠前端检查兜底。

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

总结

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

相关推荐
万联WANFLOW39 分钟前
Kimi K3.1 Pro 接口接入指南:模型选型、费用计算与零数据保留
java·spring boot·python·安全·spring·大模型
安教安全员通关宝40 分钟前
2026年浙江安全员B证考试题库+答案+解析
安全
福建佰胜张工1 小时前
费希尔 FIELDVUE™ DVC6200-AC 智能阀门定位器深度解析:双作用配置、核心参数与典型应用
运维·安全·自动化
木头科技2 小时前
【AI 工程化第十八篇】Spring AI 语音 Agent 实战:实时转写、WebSocket、流式 TTS 与打断机制
java·人工智能·安全·spring·性能优化
富安达智能2 小时前
气体传感器在智慧温室大棚中的应用,助力设施农业提质增效
安全
千里念行客2403 小时前
恩威医药:第三季度扭亏为盈,经营拐点已经写在单季报表里
大数据·科技·安全·健康医疗
2603_954708314 小时前
微能网协调控制箱的架构优势对能源管理的影响?
大数据·人工智能·分布式·安全·架构
Flynt4 小时前
PHP 9.2 分 RCE 的补丁比公告早公开 3 天,我读完 389 个文件的 diff,也把"死在代码之前"跑了出来
安全·php·源码
2601_967212724 小时前
可移动轨道插座安全结构、场景适配与安装技术说明
大数据·经验分享·安全
凯基迪科技5 小时前
STM32G系列(G0/G4)芯片解密程序提取RDP读保护解析
网络·stm32·安全