ワンクリックでGitHub OAuthトークン奪取 — VS Codeのwebview設計バグを解剖する
はじめに
2026年6月2日、セキュリティリサーチャーの Ammar Askar 氏が「github.dev で悪意あるリポジトリを開いた瞬間、GitHub の OAuth トークンが盗まれる」脆弱性をフルディスクロージャで公開した。Hacker News では 609pt を獲得し、VS Code と Cursor を日常的に使う開発者の間で警戒が広がっている。本記事では公開された攻撃チェーンを技術的に分解し、なぜこのバグが成立したのか、どこに設計上の前提崩れがあったのかを掘り下げる。
ワンクリックで何が起きるのか — 被害の全体像
被害シナリオは至ってシンプルだ。攻撃者の用意したリポジトリを、ブラウザで github.dev 上から開く(あるいはデスクトップ版 VS Code でクローンして開く)。ただそれだけで、被害者が github.dev に紐づくセッションを持っていれば、攻撃者は被害者の GitHub OAuth トークンと、そのトークンでアクセス可能な全プライベートリポジトリの一覧を取得する。
このトークンは GitHub Repositories 拡張がプリロードしている強力なものであり、プライベートリポジトリへの読み書き権限をフルに持つ。つまり一度盗まれれば、攻撃者は被害者が所属する組織のソースコードを取得・改変できる立場に立てる。CVE 番号は記事公開時点で未付与だが、Microsoft は 6 月 3 日に github.dev 側に確認ダイアログを追加し、skipPublisherTrust の悪用パスを塞いだ。デスクトップ版の根本対策はまだ完全には行き渡っていない。
被害規模が広いのは、攻撃前提条件が極めて緩いためだ。GitHub のアカウントを使って一度でも github.dev を開いたことがあるユーザーであれば、ブラウザの localStorage に OAuth トークンが残存している。そこに「面白そうな OSS のリポジトリリンク」を SNS や Issue に貼られ、不用意にクリックして github.dev に開くだけで、攻撃が成立してしまう。
5段階の攻撃チェーン — どう連鎖するのか
このバグの恐ろしさは、単一の致命的な脆弱性ではなく、複数の正常機能を連鎖させて到達している点にある。Askar 氏の解説をベースに、攻撃の流れを 5 段階に分解する。
1. Jupyter ノートブック内 webview への JS 注入
リポジトリに .ipynb ファイルを置く。VS Code はこれを開く際、ノートブックのレンダリングを webview に委ねる。ノートブック出力に埋め込まれた <img> タグの onerror ハンドラに、攻撃用 JavaScript を仕込む。これにより、webview のサンドボックス内で攻撃者制御の JS が実行される。
2. webview からメイン VS Code へのキーイベント中継を悪用
ここが核心だ。VS Code の webview は「ユーザーがフォーカスを取られたままだとキーボードショートカットが効かない」問題を避けるため、did-keydown ハンドラで keydown イベントを親ウィンドウに転送する設計になっている。webview 内の JS から dispatchEvent() で合成キーイベントを発火すれば、それが VS Code 本体に「本物のユーザー入力」として届く。
3. Ctrl+Shift+A で通知のプライマリアクションを承認
攻撃 JS は Ctrl+Shift+A を合成する。これは VS Code の Notifications: Accept Notification Primary Action コマンドにバインドされており、画面下部の通知(このときは「ワークスペース推奨拡張をインストールしますか?」)の主要ボタンを押す。リポジトリの .vscode/extensions.json に攻撃者のローカル拡張を列挙しておけば、合意ダイアログを素通りしてインストールが走る。
4. 拡張のカスタムキーバインドで skipPublisherTrust:true を叩く
インストールされた拡張は package.json の contributes.keybindings で Ctrl+F1 を自前のコマンドに割り当てておく。攻撃 JS は続けて Ctrl+F1 を合成。発火するのは workbench.extensions.installExtension で、引数に skipPublisherTrust: true を渡せる。本来は「未検証パブリッシャーの拡張を入れますか?」という警告で止めるための仕組みが、この経路だとサイレントで突破される。
5. 第2の拡張が GitHub OAuth トークンを取得・送信
インストールされた第2の拡張は、もはやサンドボックス外で動くフル機能の VS Code 拡張だ。vscode.authentication.getSession('github', ...) 系の内部 API 経由で GitHub Repositories 拡張がキャッシュしている OAuth トークンを掴み、https://api.github.com/user/repos を叩いてプライベートリポジトリ一覧を取得、外部サーバーに送信する。所要時間は webview の初期化を待つ 10 秒程度。クリックから 10 数秒で被害が完成する。
なぜこの設計が崩れたのか — 信頼境界の前提
技術的に興味深いのは、各ステップ単体は「仕様通り」に動いている点だ。webview のキーイベント中継はユーザー体験向上のための正当な機能で、ワークスペース推奨拡張も「リポジトリに合わせて開発ツールを揃える」便利機能、skipPublisherTrust フラグも内部での自動化用途を想定した API である。
崩れているのは信頼境界の前提だ。webview は本来「親プロセスより低い信頼レベルの実行環境」として扱われるべきだが、did-keydown 中継は webview 内の入力を「ユーザー本人の入力」と区別なく親に渡してしまう。つまり webview の合成イベントが「ユーザーが意図して押したキー」と等価に扱われる時点で、サンドボックスとしての隔離は事実上破られている。
加えて github.dev の場合、Microsoft 公式ホストの編集環境という権威性ゆえに、localhost ベースのデスクトップ版より広い権限(プリロード済み OAuth トークン)を持つ。この「ブラウザ製品としてのオリジン分離」と「VS Code 製品としての機能ポリシー」が、責任の谷間で噛み合っていなかったのが本質的な敗因と言える。
Askar 氏は MSRC への過去の対応に不満を持ちフルディスクロージャを選んだと書いており、その判断の是非はともかく、開発者コミュニティ側にとっては「攻撃手法を学んだうえで身を守る」材料が得られた。
エンジニアが今すぐ取るべき対応
実務上、今日中に取れるアクションは以下のとおりだ。
- github.dev の localStorage・Cookie を全削除する。ブラウザの「サイト データ」設定から
github.devと関連ドメインを消す。これで OAuth トークンの残存がリセットされ、次回アクセス時に明示的な再認証フローを経るようになる。 - 怪しい
.を含むリポジトリリンクをワンクリックで github.dev に開かない。github.comURL の.comを.devに書き換えるだけで github.dev に飛ぶため、SNS で拡散された短縮 URL や Issue 内のリンクは特に警戒する。 - VS Code デスクトップ版を最新に更新し、Microsoft の修正(確認ダイアログ追加・
skipPublisherTrustの塞ぎ込み)を取り込む。 - Cursor、Windsurf など VS Code フォークの利用者は、各フォークの更新状況を確認する。本家パッチの取り込みタイミングはフォークごとに異なる。
- 組織として GitHub Enterprise を運用しているなら、Personal Access Token と OAuth App のスコープ監査を一度走らせる。万一トークンが流出していた場合、影響範囲を最小化するためにスコープを絞っておく価値は高い。
なお、github.dev の OAuth トークンと VS Code Marketplace でインストールした「GitHub」拡張のトークンは別物だが、悪用された認証情報がどこに紐づいているかはユーザー側からは見えにくい。怪しい挙動を検知したらまず GitHub の Settings > Applications > Authorized OAuth Apps を確認するのが定石だ。
まとめ
本件は「単一の致命傷」ではなく「正当機能の連鎖」で成立した脆弱性であり、webview の信頼境界という設計上の前提が現実の脅威モデルと噛み合っていなかったことが本質だ。VS Code を使うすべての開発者は、github.dev のローカルストレージ削除と本体のアップデートを今日中に済ませておきたい。エディタは単なる作業ツールではなく、認証情報の保管庫でもある — その自覚を持つきっかけにしたい一件である。今後は Cursor などフォーク群の追従と、Microsoft 側のさらなる構造的修正に注目していきたい。
今日のその他のニュース
Gemma 4 12B が登場 — Google が画像エンコーダを別途持たない統合マルチモーダル 12B モデル「Gemma 4 12B」を公開。テキストと画像を同じトランスフォーマで処理してパスを短縮し、オンデバイス展開を狙う。Hacker News 394pt。Flutter・モバイル文脈の生成 AI 統合が一段進む。
Angular v22 リリース — Signal API が安定化し、ビルドパフォーマンスも改善。React 系のシグナル流れ(Solid、Vue ref など)と歩調を合わせる形でフロントエンド全体のリアクティビティモデルが収束しつつある。
Let’s Encrypt がポスト量子暗号証明書のロードマップを公開 — Web インフラの量子耐性移行が現実のスケジュールに乗ってきた。HN 132pt。証明書チェーンを扱うインフラ担当者は次の TLS 大型移行を視野に入れておくフェーズに入った。
ソース
- 1-Click GitHub Token Stealing via a VSCode Bug (Ammar Askar)
- VS Code zero-day lets hackers steal GitHub tokens in one click (BleepingComputer)
- One-Click GitHub Dev Attack Lets Attackers Steal Full GitHub OAuth Tokens (The Hacker News)
- 1-Click GitHub Token Vulnerability Lets Attackers Steal Users’ OAuth Tokens (CybersecurityNews)