
2026/02/21 5:39
誤設定された VSCode 拡張機能から脱却する(2023)
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
この記事は、Visual Studio Code(VS Code)で発見・公開・悪用された4つの重大脆弱性を記録した2部構成のブログシリーズです。これらの脆弱性は3つが拡張機能(SARIFビューワー、Live Preview)に影響し、1つがエディタ自体(CVE‑2022‑41042)に影響します。Microsoft はこれらの発見に対して7,500ドルの報奨金を授与しました。
4つすべての欠陥は、攻撃者が Webview サンドボックスから脱出し、ローカルファイルを外部送信したり、ユーザーのマシン全体を完全に乗っ取ったりすることを可能にします。
- SARIFビューワー:不安全な
のレンダリング(ReactMarkdown
)と許容的なescapeHtml = false
が組み合わさり、攻撃者がlocalResourceRoots
など任意のファイルを読み取れるようになります。~/.ssh/id_rsa - Live Preview: (1)
を介した HTML/JavaScript の注入で、postMessage ハンドラから srcdoc‑iframe をホストできる。CSP は nonce ベースのinnerHTML
を使用しますが、nonce をブルートフォースまたは回復することは効果的ではありません。(2) そのローカル HTTP サーバーにパス・トラバーサル脆弱性があり、ワークスペース内外から任意のファイルを読み取れます。script-src - DNS リバインディング:バックグラウンドで実行される Live Preview サーバーを利用し、CORS 制限を回避する方法としてデモンストレーションされています。
- DNS プレフェッチトリック:攻撃者は
タグを使用してサブドメインにファイル内容を埋め込みます。<link rel="dns-prefetch">
記事では、Webviews の作成、
localResourceRoots の設定、nonce の生成、および URL の解析の具体的なコードスニペットが提供されています。
Microsoft は 2022 年 8 月から 10 月の間に各脆弱性を別々のコミット(c054421/98816d9 – SARIF; 4e029aa – Live Preview; 9d26055/88503c4 – コアバグ)で修正しました。
推奨される緩和策: CSP を強化(nonce/hash の使用、unsafe‑inline の回避)、
localResourceRoots を拡張機能フォルダに限定、任意の innerHTML をサニタイズ、postMessage ハンドラを検証、厳格な URL 解析を実施、ローカルサーバーのポート番号をランダム化、およびホストヘッダー許可リストを設定します。
次の記事では、拡張機能が正しく構成されている場合でも Webview サンドボックスを回避する VS Code コアバグについて検証します。
本文
TL;DR
この2部構成のブログシリーズでは、VSCode 拡張機能(SARIF Viewer と Live Preview)における3つの脆弱性と、VSCode 本体に対する1つの脆弱性(CVE‑2022‑41042、賞金 7,500 USD)をどのように発見し報告したかを解説します。記事ではそれぞれの欠陥の根本原因を特定し、攻撃者がマシンを乗っ取るために実際に利用できるエクスプロイト例を提示するとともに、同様の問題を防ぐ方法を推奨しています。
VSCode 拡張機能のセキュリティが重要な理由
VSCode の拡張機能はフルファイルシステムとシェルへのアクセス権を持ちます。攻撃者が拡張内で JavaScript を実行できれば(例:XSS 経由)、ホストシステムを完全に乗っ取ることが可能です。
Microsoft の SARIF Viewer と Live Preview を監査した際、悪意のあるウェブサイトを閲覧中に拡張機能が動作しているときに、ローカルファイル(SSH キーも含む)をすべて盗み取ることができる高い深刻度のバグを発見しました。
VSCode Webview – ざっくり復習
- サンドボックス化された UI パネル(
と同様)。<iframe> - Webview 内では Node.js API が無効化され、ファイル読み込みやコマンド実行はメイン拡張のみが行える。
- セキュリティオプション:
– スクリプトを許可するか(デフォルトはenableScripts
)。true
– ファイルアクセス先を制限(デフォルトはワークスペース+拡張フォルダ)。localResourceRoots- Content‑Security‑Policy (CSP) – 画像、CSS、スクリプト等のソースを限定。
Webview は
postMessage() を介してメイン拡張と通信します。
脆弱性 1 – SARIF Viewer における HTML/JavaScript 注入
何が壊れていたか
ビューアは ReactMarkdown の
escapeHtml={false} を使用して SARIF 結果の説明を描画しています。これにより、悪意ある SARIF ファイルを開くと任意の HTML と JavaScript が注入できるようになっていました。
証明実験
不正なソースを持つ
<img> に onerror ハンドラを設定すると、Webview 内で JavaScript を実行できます。
エスカレーション – ローカルファイルの漏洩
- Webview の
が誤って全パス(例:localResourceRoots
)へのアクセスを許可していた。z:\ - Webview から
に fetch を送ると、ファイル内容が取得できました。https://file+.vscode-resource.vscode-cdn.net/<path> - CSP はアウトバウンドリクエストを禁止していましたが、DNS‑prefetch
タグでサブドメインにペイロードを埋め込むことで回避しました。<link>
HTML 注入・パストラバーサル・DNS エクスフィルトレーションの組み合わせにより
~/.ssh/id_rsa などのファイルを盗み取ることが可能でした。
修正と検知
を拡張フォルダまたはワークスペースのみへ限定。localResourceRoots- Markdown のレンダリング時に
を使用。escapeHtml={true} - CSP ノンスは暗号学的に安全な RNG(例:
)で生成。crypto.randomBytes
Semgrep の更新された ReactMarkdown ルール(PR #2307)は同様の問題を自動検知できます。
脆弱性 2 – Live Preview における HTML/JavaScript 注入
何が壊れていたか
Live Preview はポート 3000 上でローカル HTTP サーバーを起動し、
<iframe> を埋め込んでいます。拡張の link-hover-start メッセージハンドラはユーザー入力を直接 Webview の innerHTML にコピーし、サニタイズが行われていませんでした。
JavaScript の実行
タグを直接挿入しても Webview 内では実行されません。<script>- 代わりに srcdoc iframe を注入すると、ブラウザは同一オリジンとして扱うため、そのスクリプトが Webview コンテキストで実行できます。
CSP の課題 – ノンス
Webview の CSP は
Math.random() で生成された 64 桁のノンスを使用。ブルートフォースは非現実的で、Math.random() の状態復元も失敗します(iframe、外部 Webview、メイン拡張それぞれが独自 RNG を持つため)。
結果
srcdoc iframe で HTML 注入とスクリプト実行は可能でしたが、CSP により完全なエクスプロイトは阻止されました。次の脆弱性では別のベクトルを突きます。
脆弱性 3 – Live Preview のローカル HTTP サーバーにおけるパストラバーサル
何が壊れていたか
サーバーは
http://127.0.0.1:3000/?../../../../../../etc/passwd? のような URL を受け取り、手書きのクエリ解析により /etc/passwd を解決します。通常ブラウザは ../ を正規化しますが、サーバー側ではその処理を行っていません。
攻撃シナリオ
| シナリオ | 仕組み |
|---|---|
| 攻撃者がファイルを制御 | 悪意ある HTML ファイルからローカルサーバー経由で任意のホスト上のファイルを取得し、漏洩させる。 |
| DNS リバインディング | 攻撃者サイトをホストし、DNS を と の間で切り替える。Live Preview が動作中にサイトへアクセスすると、ドメインが localhost に解決された瞬間にトラバーサル攻撃が実行されローカルファイルが漏洩。 |
どちらもサーバーがパスを正規化せず、許可されたルート内にあるかどうかを確認しない点に依存しています。
VSCode Webview を安全に保つ方法
| ガイドライン | 推奨 |
|---|---|
| CSP | から始め、 は避ける。ノンスやハッシュは で生成。 |
| localResourceRoots | 拡張のインストールフォルダに限定。任意のファイルシステムパスを公開しない。 |
| postMessage ハンドラ | すべての入力を検証。SQL/コマンド注入、任意ファイル読み書きを防止。 |
| ローカル HTTP サーバー | クラスで URL を解析し、正規化後に解決パスが許可されたルート内にあるか確認。 |
| DNS リバインディング対策 | ランダムポートで起動し、静的ポートへ する。Host ヘッダーを に限定し、認証も検討。 |
| innerHTML へのユーザー入力は避ける | を使用するか、適切なサニタイズライブラリで処理。 |
これらの原則に従うことで、上記で示したような攻撃を受けにくい拡張機能が構築できます。
タイムライン(参考)
- 2022 年8月12日 – Microsoft に脆弱性 1 を報告
- 2022 年8月13–16日 – コミット
とc054421
で修正98816d9 - 2022 年9月7日 – 脆弱性 2・3 を報告
- 2022 年9月14日 – 脆弱性 2(コミット
)を修正4e029aa - 2022 年10月5日 – 脆弱性 3(コミット
と9d26055
)を修正88503c4
次回の投稿では、拡張機能が正しく構成されている場合でも Webview のサンドボックスから脱出できる VSCode 本体のバグについて検証します。