Hotdry.

Article

VSCode URL 处理器漏洞:Webview 边界绕过与 GitHub Token 一键窃取机制

分析 VSCode Webview 消息代理机制缺陷导致的 GitHub OAuth Token 窃取漏洞,剖析同源策略绕过路径与键盘事件注入攻击链,提供可落地的防护参数与审计清单。

2026-06-03security

背景:github.dev 的权限模型隐患

GitHub 提供的 github.dev 是一个基于浏览器的轻量级 VSCode 实例,用户只需将仓库 URL 从 github.com 改为 github.dev 即可在浏览器中打开代码编辑器。该功能通过 GitHub 向 github.dev POST 传递 OAuth Token 实现身份认证,使用户能够浏览私有仓库、提交代码和发起 Pull Request。

关键问题在于:这个 OAuth Token 并非限定于特定仓库,而是具有访问用户所有仓库(包括私有仓库)的完整读写权限。当 github.dev 加载时,Token 被存储在浏览器本地存储中,供后续 API 调用使用。这种设计使得 github.dev 成为攻击者的诱人目标 —— 一旦能够在这个 Web 应用中执行任意代码,就能窃取到具有高权限的访问凭证。

Webview 安全模型与边界设计

VSCode 使用 Webview 作为沙箱机制来渲染不受信任的内容(如 Markdown 预览、Jupyter Notebook 输出)。Webview 实际上是一个 <iframe>,其 origin 为 vscode-webview://...,与主窗口的 vscode-file://...vscode-app 不同源。这种跨源隔离确保了 iframe 内的 JavaScript 无法直接访问主窗口的 DOM 或调用 Node.js API。

为了实现 Webview 与主编辑器之间的交互(如 Markdown 预览同步滚动、Jupyter 单元格交互),VSCode 使用 Window.postMessage() API 进行跨窗口通信。主窗口可以向 Webview 发送消息,Webview 也可以向主窗口发送消息,双方通过约定的事件类型进行协作。

漏洞核心:键盘事件代理链的滥用

问题的关键在于 VSCode 为了提升用户体验,实现了一套键盘事件转发机制。当用户在 Webview 内点击后,期望能够正常使用快捷键(如 Ctrl+Shift+P 打开命令面板)。由于跨源策略阻止了父窗口监听 iframe 内的键盘事件,VSCode 的解决方案是在 Webview 内监听 keydown 事件,然后通过 postMessage 将按键信息转发给主窗口。

Webview 内的代码如下:

contentWindow.addEventListener('keydown', handleInnerKeydown);

const handleInnerKeydown = (e) => {
    hostMessaging.postMessage('did-keydown', {
        key: e.key,
        keyCode: e.keyCode,
        code: e.code,
        shiftKey: e.shiftKey,
        altKey: e.altKey,
        ctrlKey: e.ctrlKey,
        metaKey: e.metaKey,
        repeat: e.repeat
    });
};

这意味着运行在 Webview 内的不受信任 JavaScript 可以通过构造 KeyboardEvent 并派发到 window 对象,来模拟用户按键行为。主窗口无法区分这些事件是真正的用户输入还是脚本模拟的,从而打开了攻击面。

攻击链:从 Notebook 到 Token 窃取的完整路径

攻击者构造的利用链包含多个阶段,每个阶段都利用 VSCode 的合法功能来推进攻击:

阶段一:初始访问与代码执行

攻击者诱导受害者点击指向 github.dev 上恶意仓库的链接,该仓库包含一个 Jupyter Notebook。Notebook 中的 Markdown 单元格嵌入了恶意 JavaScript:

<img src="data:foobar" onerror="/* malicious code */">

这段代码在 Webview 渲染时执行,获得了在 vscode-webview:// origin 内运行代码的能力。

阶段二:扩展推荐与通知接受

恶意仓库包含 .vscode/extensions.json 文件,推荐安装攻击者控制的扩展:

{
  "recommendations": [
    "HackerMan.my-malicious-extension"
  ]
}

当 github.dev 加载仓库时,会弹出通知询问是否安装推荐扩展。恶意脚本等待数秒后,模拟发送 Ctrl+Shift+A(Notifications: Accept Notification Primary Action 的默认快捷键)来点击 "安装" 按钮。

阶段三:绕过发布者信任检查

VSCode 1.97 引入了发布者信任系统,首次安装新发布者的扩展时会弹出确认对话框。攻击者利用 "本地工作区扩展" 功能 —— 将扩展文件放在 .vscode/extensions/ 目录下 —— 该功能在受信任工作区内跳过发布者信任检查。

阶段四:自定义 Keybind 与恶意扩展安装

本地工作区扩展的 package.json 定义了自定义键盘绑定:

{
  "contributes": {
    "keybindings": [
      {
        "key": "ctrl+f1",
        "command": "runCommands",
        "args": {
          "commands": [
            {
              "command": "workbench.extensions.installExtension",
              "args": ["Attacker.ext", {"context": {"skipPublisherTrust": true}}]
            }
          ]
        }
      }
    ]
  }
}

恶意脚本再次模拟按键(Ctrl+F1),触发安装另一个扩展,该扩展具有访问 VSCode API 的完整权限,可以读取存储在内存中的 GitHub OAuth Token 并发送到攻击者服务器。

影响范围与风险评估

该漏洞影响 github.dev 的浏览器版本和桌面版 VSCode。在浏览器版本中,攻击只需用户点击一个链接即可触发;在桌面版中,需要用户克隆恶意仓库并打开其中的 Notebook 文件,攻击门槛相对较高。

被窃取的 GitHub OAuth Token 具有完整读写权限,攻击者可以:

  • 读取用户的所有私有仓库代码
  • 向仓库写入恶意代码
  • 删除仓库或修改设置
  • 以用户身份执行其他 GitHub API 操作

对于已授权 github.dev 的用户,当前没有 CSRF Token 或其他防护机制阻止这种攻击。只有在首次访问时出现的登录确认对话框能够提供一层保护,但大多数开发者已经授权过该服务。

防护建议与可落地参数

即时缓解措施:

  1. 清理站点数据:在 Chrome 中点击地址栏左侧的站点信息图标 → "Cookies 和网站数据" → "管理设备上的网站数据",删除所有 github.dev 相关条目。这将强制下次访问时重新显示登录确认对话框。

  2. 审查已安装扩展:检查 VSCode 中已安装的扩展,移除来源不明或不再使用的扩展。特别关注近期自动安装的扩展。

长期安全实践:

  1. 最小权限原则:定期审查 GitHub 个人访问令牌和 OAuth 应用的权限范围,撤销不必要的授权。

  2. 仓库来源验证:在打开来自邮件、社交媒体或聊天工具的 github.dev 链接前,验证仓库来源的可靠性。

  3. 企业环境加固:对于使用 VSCode 的企业环境,考虑通过策略限制本地工作区扩展的安装,或禁用自动扩展推荐功能。

检测指标:

  • 监控 GitHub 账户的 OAuth 应用授权记录
  • 关注异常的 API 调用模式(如短时间内大量仓库枚举请求)
  • 检查 VSCode 扩展目录中是否存在可疑的本地扩展

技术反思:UX 与安全的平衡

这个漏洞揭示了现代 IDE 安全模型中的一个普遍张力:用户体验与严格安全边界之间的权衡。VSCode 选择转发键盘事件以确保快捷键在 Webview 内正常工作,这本是一个合理的 UX 决策,但攻击者找到了滥用这一机制的路径。

防御此类攻击需要在架构层面进行改进:

  • 对通过 postMessage 接收的键盘事件增加来源验证和速率限制
  • 敏感操作(如扩展安装)需要更严格的用户确认机制,不能仅依赖可被模拟的键盘事件
  • 考虑为高风险操作引入额外的验证层(如点击确认而非键盘确认)

该漏洞目前尚未分配 CVE 编号,Microsoft 也未发布官方补丁。在补丁可用之前,用户应遵循上述缓解措施保护自身安全。


参考来源:

  • Ammar Askar 的技术分析博客:"1-Click GitHub Token Stealing via a VSCode Bug" (blog.ammaraskar.com/github-token-stealing/)
  • BleepingComputer 新闻报道:"VS Code zero-day lets hackers steal GitHub tokens in one click" (bleepingcomputer.com)

security

内容声明:本文无广告投放、无付费植入。

如有事实性问题,欢迎发送勘误至 i@hotdrydog.com