1 ポイント 投稿者 GN⁺ 3 시간 전 | 1件のコメント | WhatsAppで共有
  • github.dev は github.com から渡される OAuth トークンでブラウザ版VSCode上のファイル閲覧、PR、コミットを実行し、このトークンは特定のリポジトリに限定されないため、ユーザーがアクセス可能なすべてのリポジトリを読み書きできる
  • VSCode webview は vscode-webview://... iframe で分離されているが、キーボードショートカットのUXのために webview の keydowndid-keydown メッセージとしてメインウィンドウに転送しており、信頼されていないスクリプト がユーザーのキー入力のようにイベントを送信できる
  • 任意のテキスト入力は HTML <input> のため通用しないが、デフォルトのショートカット Ctrl+Shift+A、おすすめ拡張機能のインストール通知、local workspace extensions、カスタムキーバインドを組み合わせることで拡張機能のインストールコマンドを実行できる
  • PoC は Jupyter notebook のMarkdownセルで JavaScript を実行しておすすめ拡張機能のインストールを承認し、新しいキーバインドで選択した拡張機能をインストールした後、GitHub API トークンとプライベートリポジトリ一覧を表示する
  • デスクトップ版VSCodeにも同じ脆弱性があるが、攻撃者はリポジトリの複製と notebook のオープンを誘導する必要があり、github.dev ユーザーはサイトデータを削除して初回確認ダイアログを再表示させる防御が必要

脆弱性の概要

  • github.dev は、アクセス可能な GitHub リポジトリURLを github.com から github.dev に変えるか、メニュー項目をクリックすると、ブラウザ上で動作する軽量版VSCodeを開く
  • このブラウザ版VSCodeではリポジトリのファイルを閲覧でき、プライベートリポジトリも開けて、PRの送信やコミットの作成も可能
  • github.com はユーザーの代わりに GitHub とやり取りできる OAuth トークンを github.dev に POST し、このトークンはユーザーがやり取りしていた特定のリポジトリに限定されない
  • 攻撃者はリンクのクリックだけで読み書き権限を持つ GitHub トークンを窃取でき、対象にはプライベートリポジトリも含まれる

Webview分離とキー入力転送の問題

  • VSCode webviews はメインのVSCodeウィンドウとは異なる origin の <iframe> を使って JavaScript 実行を分離する
  • Jupyter notebook の出力は vscode-webview://... origin の <iframe> でレンダリングされ、メインの Electron ウィンドウは vscode-file://... origin を使う
  • この分離のおかげで、notebook が HTML 表示や JavaScript ベースのインタラクティブウィジェットを使っても、iframe 内から Electron の Node.js API や VSCode API を呼び出すことはできない
  • Markdown プレビューのようにメインウィンドウと webview が協調する必要がある機能は、Window.postMessage() API でメッセージをやり取りする
  • VSCode は webview 内をクリックした状態でも Ctrl+Shift+P のようなショートカットが動作するよう、did-keydown イベントをメインウィンドウへ転送する
  • webview 内の信頼されていないスクリプトは keydown イベントを直接発火させ、ユーザーがキーを押したかのように偽装できる

攻撃チェーン

  • Ctrl+Shift+P でコマンドパレットを開くことはできるが、コマンドパレットは HTML <input> を使うため、任意の文字列を入力する方法は通用しない
  • 矢印キーや Enter のように keydown で処理される入力は使え、VSCode のデフォルトショートカット群も活用できる
  • Ctrl+Shift+A は「Notifications: Accept Notification Primary Action」のデフォルトキーバインドで、最後のVSCode通知の主要ボタンを押す
  • .vscode/extensions.json におすすめ拡張機能を入れると VSCode がインストール通知を表示するが、VSCode 1.97 の publisher trust システムは新しい publisher の拡張機能をインストールする際に別途信頼ダイアログを表示する
  • Tab でボタン移動はできても、「Trust Publisher & Install」ボタンの Enter 処理はボタン自身の keydown に結び付いているため、この経路だけでインストールを完了するのは難しい
  • local workspace extensions は、信頼された workspace 内の .vscode/extensions にある拡張機能を直接インストールでき、github.dev/web workspace は常に信頼済み状態になっている
  • ローカル workspace 拡張機能を直接実行しようとすると、extension worker が vscode-cdn.net 由来の拡張機能を想定しているため CSP エラーが発生する
  • 代わりに、ローカル workspace 拡張機能の package.json にカスタムキーバインドを追加し、そのキーバインドが workbench.extensions.installExtensionskipPublisherTrust コンテキストで呼び出すようにできる

PoCの動作と影響

  • 必要な構成は Jupyter notebooklocal workspace extension を含むリポジトリである
  • notebook のMarkdownセルは画像の onerror 属性を通じて JavaScript を実行できる
  • ペイロードは、VSCode がおすすめ拡張機能のインストール通知を表示するまで待機した後、Ctrl+Shift+A イベントを送り、通知の主要アクションを承認する
  • その後、拡張機能がインストール・有効化され、カスタムキーバインドが反映されるまで待機し、Ctrl+F1 イベントで選択した拡張機能のインストールをトリガーする
  • PoC でインストールされた拡張機能は GitHub API トークンを取得し、https://api.github.com/user/repos を照会してアクセス可能なプライベートリポジトリを取得した後、トークンとリポジトリ一覧を情報ボックスに出力する
  • PoC 実行後は github.dev のデータを消去するか PoC 拡張機能を削除する必要があり、削除しないとすべての github.dev ページに残り続ける
  • デスクトップ版VSCodeにも同じ脆弱性があるが、攻撃者は被害者にリポジトリを clone させ、webview スクリプトペイロードを含む notebook を開かせる必要がある
  • 被害者が開く webview に別の XSS があれば、デスクトップでも実質的に完全なリモートコード実行につながる可能性がある

防御と緩和要素

  • 過去に github.dev を使ったことがなければ、サイトに入る際にクリックが必要なダイアログが1つあり、攻撃ページから離脱する機会が生まれる
  • github.dev のCookieとローカルサイトデータを削除すると、この初回ダイアログを再表示できる可能性がある
  • Chrome では URL バーのアイコンを押して Cookies and site data > Manage on-device site data に進み、関連ドメインのデータを削除できる
  • すでに github.dev のダイアログを通過しており、ブラウザのローカルストレージを消していない場合、github.dev には CSRF トークンのような保護がないため、インターネット上のどのリンクからでも攻撃へリダイレクトできる
  • VSCode は iframe 分離だけに依存せず、厳格な Content Security PolicyDOMPurify も併用している
  • 拡張機能ページのMarkdownプレビューでは script-src 'none' を使って任意の JavaScript 実行を防いでいるため、拡張機能リンクだけでデスクトップ版の1クリックRCEになるより大きな影響は防がれている

公開の背景とスケジュール

  • MSRC は過去の VSCode バグ報告をひそかに修正し、クレジットを与えず、セキュリティへの影響なしと表示していた
  • 最近の StarlabsのVSCode XSSバグ報告 も不適格かつ低重大度として扱われた
  • VSCode チームには UI/UX とセキュリティの間でバランスを取る時間がさらに必要だった可能性はあるが、セキュリティ研究者の時間と労力を当然視すべきではないという理由から、完全公開が選ばれた
  • 2026年6月2日の公開1時間前に、GitHub セキュリティ側の既存の連絡先へ公開予定が伝えられた
  • 同日、脆弱性が公開され、VSCode issue tracker にも登録された

1件のコメント

 
GN⁺ 3 시간 전
Hacker Newsの反応
  • よくまとまっているし、大きく見れば、Webに埋め込まれたVSCodeエディタがGitHubにログイン済みであること自体が残念
    多層防御の有無とは別に、その原罪のせいで攻撃対象領域が大きく広がっている。悪意あるNPMパッケージが見つけられるように、ワークステーション上に全権限を持つGitHub APIトークンを平文で置いているのと似ている
    理想を言えば、ブラウザIDEはそのリポジトリに対するpull/pushだけが可能な一時的なリポジトリ単位の権限スコープやトークンで動き、github.comのWebセッションはまったく持たないでほしい。GitHubの完全なWeb UIが必要ならgithub.comに戻り、github.devは単一リポジトリのサービスとして置く、という形がよさそう
    ただし、ユーザーにとって不便で、実装も難しく、github.devのツール全般に歴史的に埋め込まれた前提である可能性が高い

    • Codespacesは実際にそうしている。トークンは有効化したCodespaceのリポジトリに対する読み書き権限しか持たない [1]
      github.devでもこの方式を真剣に検討すべき
      [1] https://orca.security/resources/blog/hacking-github-codespac...
    • 悪意あるNPMパッケージの問題は今後さらに深刻化しそう。最近、OpenCodeのようなAI実行ツールがバックグラウンドで任意のnpmパッケージをダウンロードし、ホームディレクトリやプロジェクトディレクトリのあちこちにばらまいているのを見たが、ユーザーに通知も確認もしていなかった
      さらに悪いのは、開発者たちでさえあまり気にしていないように見えること
    • 自分のリポジトリを開くときにログイン済みなのは構わないが、他人のアカウントのリポジトリを開くときまでそうであってはいけないと思う。そしてwebviewのキーボードショートカットも、無害なキー割り当てだけを許可し、どのkeydownハンドラにも伝播しないよう修正すべき
      デスクトップではElectronが直接横取りするように変えて、この機能は削除したほうがよく、Webではデフォルトで無効化するのが妥当だと思う
    • SSHキーとGitHub deploy keyを使えば、ある程度は似た形にできる。安全性まで断言はできないが、全リポジトリにアクセスできるGitHub設定をしたことはない
      他のGitホスティングにも同様の機能があるかはよく分からない
    • そのリポジトリでpullは可能でも、pushはトークンではなく、ユーザーが最終的にpushできるステージング領域にしか行えないようにしたらどうかと思う
      正直、LLMエージェントもこうあるべき。LLMに直接pushさせるのは無謀に見える
  • この攻撃が特に厄介なのは、VSCode拡張機能がエディタ本体と同じ信頼レベルで実行され、しかも大半の開発者が権限を確認していない拡張機能を何十個もインストールしている点
    悪意ある、あるいは乗っ取られた拡張機能がGitHubトークンをひそかに流出させても、ネットワーク監視がなければ気づきにくく、拡張機能は隔離されたプロファイルで実行すべきだという根拠になる

    • ネットワーク監視があっても、GitHub自体へ流出されると防ぐのは非常に難しい。SSLインターセプトと非常に厳格なURL許可リストがなければ、なおさらだ
      最善の方法はGitHubから離れ、セルフホストの内部GitLab/Forgejoに移行し、GitHubを完全に遮断すること
  • 最近、似たようなことを経験した。GitHubトークンとCloudflareトークンが盗まれた
    セキュリティを本気でやっていても、十分に長い時間があれば結局やられるものだと思う。最善策は分離し、被害範囲を制御すること
    誰も、何も信用せず、OrbStackを使い、トークンはいずれ漏洩する前提で常に作業すべき
    ワークフローは完全に寸断されたが、幸い、トークンを持っていった側はスパムボットに近かったようだ。偽のスパムページを大量に作り、暗号通貨のマイニングを試みていた
    何より強く残る感情は、侵害されたという感覚。みんな気をつけてほしい

    • GitHub Pagesのようなページだったのか気になる。アカウントにリポジトリが作成されていたのか? トークンが盗まれたとどうやって気づいたのかも気になる
  • MSRCにVSCodeのバグを報告したとき、ひっそり修正されてしまうというひどい経験だった、という話は典型的なMSRCらしさがある。研究者がどうせ無償で報告してくると分かっていて、わざわざ変える理由がないと考えているように見える

    • MSRCがバグを修正するわけではない
      この件の詳細は分からないが、以前BountysourceやHackerOneを通じてバグバウンティプログラムを運営していたことがある。ときどき、セキュリティチームが十分に評価する前に、報告書が先に開発チームへ流れてしまうことがある
      その時点で開発者がひっそり修正してしまうことがある。セキュリティバグに関わると自分の評価が悪く見えたり、昇進の機会に影響したりするのではないかという、合理的かどうかは別として、懸念が理由のこともある。結果として、セキュリティチームが再現しようとする頃には、脆弱性はすでに消えている
      MSRC側から見えるのは、提供された再現手順がもはや動作しないということだけ。内部のバグ履歴や、誰かがすでにパッチを当てたかどうかは見えない。そのため、本来は正当な発見であっても、報告は無効として閉じられてしまう
    • 長い間それが現状維持だったが、面倒なセキュリティ研究者たちが名声ではなく報酬を求め始めた
  • このエクスプロイトに費やした時間を事実上寄付して、VS Codeのセキュリティ対応改善の必要性を知らせてくれたことに感謝したい。諦めることもできたのに、なお助けようとしている

    • この脆弱性を売ったり寝かせたりするつもりはない。ただ、概念実証を作るのに何時間もかかることがあり、ベンダーがひっそりパッチを当てるだけで、クレジットも認知も与えてくれないと、本当に嫌な気分になる
  • なぜもっと多くの開発者が Neovim を試さないのか、正直よく分からない。
    好みの問題かもしれないが、何がインストールされていて何が実行中なのか把握できる小さな構成が良い。VSCode、ブラウザ IDE、拡張、同期、トークン、任意のプラグインが混ざると、何が何にアクセスしているのか分かりにくくなる

    • 数年前に VS Code をやめて Neovim に移った。VS Code が、デフォルトの型定義がないライブラリのために任意の Python パッケージを自動インストールすると知った後だった。
      それは Microsoft 公式の Python 拡張の機能で、他の面ではまだまともに使えるほぼ唯一の拡張だったが、自分のプロジェクトで使っているものとは違うバージョンのライブラリの型定義をインストールしていた。検証されていないサードパーティコードを平然と実行しているように見えて非常に不安だったし、設定で無効にもできなさそうだった。
      「その後は振り返らなかった」と言いたいところだが、正直ここ 1〜2 年は Neovim がほぼアップグレードのたびに自分の設定を定期的に壊すようになっている。いつかそうなる気配はあった。厳密には 10 年経っているのに nvim はまだ最初の安定版を出しておらず、だから不安定さを責めることはできないが、覚えておく価値はある。
      素の Vim に戻るべきか考えている。便利な機能はかなり失うだろうが、仕事の途中で壊れた機能をデバッグしなければならない場面は減ってほしい
    • Helix はかなり気に入っている。Neovim を深く掘り下げたわけではないが、Helix には Vim でいつも物足りなかった IDE 的な機能がかなりしっかり入っている。
      プラグインを大量に入れたり SpaceVim のようなものを使ったりする必要がない。一度試してみると気に入るかもしれない
    • ソフトウェアの習慣を変えるのはかなり難しいと感じる。覚えるべきショートカットがあり、最初は遅く感じるので、「今より良くない」という感覚が強化される。
      nvim に慣れるには時間がかかるが、慣れればより速い。それでも多くの人が居心地のいい領域にとどまる理由はよく分かる
  • 完全公開 は良い判断だったと思う。MSRC に不満を持つ人があまりにも多く、Nightmare Eclipse の件のように、もう今にもあふれ出しそうになっている。
    こうした公開が積み重なれば、MSRC が自省して自分たちこそ問題だと気づくかもしれない。可能性は低そうだが、期待することはできる

    • これが依然として最善のアプローチかどうかはよく分からない。以前の XSS 提出との比較から「低」評価になると予想して、そもそも提出すらしなかったようだ。
      それでも少なくとも試してみるか、公開する数日前には知らせておくべきだったと思う。どうなるかは分からないのだから
  • 記事はとても良かったが、最後の部分で少し混乱した。自分の理解が合っているか確認したい。
    著者は、新しい発行元信頼システムのせいで、ショートカットのトリックだけでは悪意ある拡張を直接インストールできないと言っており、発行元チェックのないローカルワークスペース拡張でこれを回避できるが、CSP に阻まれるとも言っていた。
    解決策は、「発行元確認なしで拡張をインストールする」ショートカットをバインドする ローカルワークスペース拡張 をインストールすることに見える。
    つまり、1) 拡張が 2 つ必要という意味なのか気になる。1 つ目はキー バインドだけを行うローカル拡張で、2 つ目は実際の悪意ある拡張であり、CSP のためローカルである必要はなく、実際ローカルにはできないのか。2) CSP はローカル拡張の JS だけを止めて、package.json やショートカット追加機能までは止めないのか、という点が気になる

    • 1 と 2 で合っている。概念実証リポジトリを見ればよい: https://github.com/ammaraskar/github-dev-token-steal-poc/tre...
      最も直接的な実行のために my-extension/extension.js を入れてみることはできるが、CSP によって阻まれる。ただし、script-src CSP はスクリプトだけを止めるものなので、package.json の取得は許可される。そのため、それを利用してキー バインドを提供している
  • MSRC の状況 は本当に信じがたい。
    もっと良い資料もあるだろうが、The Primeagen のこの動画は良い導入資料だと思う。
    https://www.youtube.com/watch?v=9kxx5xp5nTQ

  • 「この動作を許可する唯一の方法は、異なるオリジンの 2 つのウェブページが Window.postMessage() API で協調することだ」という部分には、小さな nitpick がある。
    iframe や親ウィンドウが location.anchor プロパティを変更する方法でも通信できる