本文へ移動
English version →
重大 9.1 急ぎ度: 早めに

Viteの開発サーバーにRCE脆弱性、修正版を公開

Viteの開発サーバーをネットワークに公開していると、HTTPリクエストだけでサーバー上の任意のコードを実行されるおそれがあります。該当する開発チームは系列ごとの修正版へ更新し、--hostの使用箇所も点検してください。

GHSA-p4f5-76q4-ffq7 公開 更新 執筆・監修: 佐々木 航 人が監修しながらAIを活用して執筆
画像は生成 AI で作成したイメージです

急ぎ度: 早めに

CVSS v4は9.1のcriticalで修正版も出ていますが、対象は開発サーバーをネットワークに公開している環境に限られるため、至急ではなく早めの更新が妥当です。

関係があるか

Viteで開発している組織のうち、--hostやserver.hostで開発サーバーをネットワークに公開しているチームが対象です。スマートフォン実機での確認や、コンテナ・仮想マシン経由で使っている環境が当てはまりやすいでしょう。

製品影響を受ける版修正版
vite(npm)8.3系 8.3.7より前の版 8.3.7(Rolldown 1.2.17の修正に依存)
vite(npm)8.2系 8.2.5より前の版 8.2.5(Rolldown 1.2.17の修正に依存)
vite(npm)8.1系 8.1.7より前の版 8.1.7(Rolldown 1.1.7の修正に依存)
vite(npm)7.3系 7.3.8より前の版 7.3.8
vite(npm)6.4系 6.4.6より前の版 6.4.6
vite-plus(npm) 1.5.1より前の版 1.5.1

確かめ方

  1. 1プロジェクトで使っているViteの版を確認します。直接の依存だけでなく、ほかのパッケージ経由で入っている版も見ます。
  2. 2package.jsonのスクリプト、Dockerfile、docker-compose、CIの設定、vite.configに、--hostやserver.hostの指定がないかを探します。
  3. 3指定がある場合は、その開発サーバーにどこからアクセスできるかを確認します。社内ネットワークや共有の検証環境から届くなら、該当すると考えてください。
  4. 4影響を受ける版の下限や、6.4系より古い系列の扱いはGitHubのセキュリティアドバイザリ(GHSA-p4f5-76q4-ffq7)で確認してください。

何が起きたか

Viteの開発サーバーに、HTTPリクエストを送るだけでサーバー上の任意のコードを実行されてしまう脆弱性があります。分類はCWE-116(出力の不適切なエンコードやエスケープ)で、CVSS v4は9.1です。

Viteには、ブラウザー向けの互換処理や省略可能な依存関係を扱うために、__vite-browser-external:と__vite-optional-peer-dep:という2種類の仮想モジュールがあります。これらはURLから取り出したモジュールIDをそのままコードに埋め込んでおり、エスケープがありませんでした。そのため、IDに任意のコードを紛れ込ませることができました。

Viteは自分が生成したモジュールのコードを信頼して扱うので、混入したコードが2つの問題につながります。1つ目は、モジュールが参照するファイルがserver.fsのチェックを通ってしまい、許可リストの外にあるファイルを取得できることです。2つ目は、new Workerやimport.meta.globの値を取り出すために使われるevalで、混入したコードがサーバー上で評価されることです。Viteはexportsやrequireなどの一部を使えなくしていますが、これはセキュリティ上の境界ではなく、回避する方法があると説明されています。

Vite 8では、問題のコードがRolldownのバイナリ内にあります。このコードはViteだけが使う前提のため、Rolldownとは別の報告として扱われていません。

攻撃の流れ

  1. 1

    開発サーバーが公開

    `--host`などの指定で、開発サーバーにネットワークから届く状態になっています。

  2. 2

    細工したURLを送信

    仮想モジュールのIDに特別な値を含むHTTPリクエストを、開発サーバーへ送ります。

  3. 3

    コードが混入

    IDがエスケープされずに仮想モジュールへ埋め込まれ、攻撃者のコードが紛れ込みます。

  4. 4

    読み出しと実行

    許可リスト外のファイルが取得され、サーバー上でコードが評価されます。

公開されている情報をもとにした流れの例です。

どう悪用されるか

アドバイザリが挙げる条件は、開発サーバーが--hostまたはserver.hostでネットワークに明示的に公開されていることです。そのサーバーにHTTPリクエストを送れる位置にいれば攻撃が成り立つ、という書き方で、ログインや利用者の操作を前提にするとは書かれていません。

成功すると、server.fsの許可リストの外にあるファイルが読み出され、サーバー上で任意のコードが実行されます。開発サーバーを動かしている端末やコンテナの権限で動くため、ソースコード、.envなどの設定ファイル、端末に置かれた認証情報が危険にさらされます。

今すぐやること

  1. 1

    使っているViteの版を確認する

    リポジトリごとに、Viteがどの版で入っているかを確認します。ほかのパッケージ経由で入る場合もあるため、依存関係の一覧で見るのが確実です。

    npm ls vite
  2. 2

    系列ごとの修正版に更新する

    使っている系列に合う修正版へ更新し、ロックファイルも更新して、CIや共有の開発環境にも反映します。vite-plusを使っている場合は1.5.1に更新します。

  3. 3

    開発サーバーの公開設定を洗い出す

    --hostとserver.hostの使用箇所を探し、本当にネットワークへ公開する必要があるかを見直します。コンテナ用の設定ファイルやCIのスクリプトも対象です。

    grep -rn -e "--host" -e "server.host" --include=package.json --include=*.config.* --include=Dockerfile* .
  4. 4

    公開していた環境の秘密情報を点検する

    更新前に開発サーバーを社内ネットワークなどへ公開していた場合は、その端末に置かれた.envやトークンなどの扱いを見直します。不審なアクセスの記録がないかも調べます。

すぐ更新できないとき

すぐに更新できないときは、開発サーバーを--hostやserver.hostでネットワークに公開しないようにします。外から確認する必要があるなら、ファイアウォールやVPNでアクセス元を絞るなど、信頼できる相手だけが届く状態にしてください。

背景

Viteはフロントエンド開発で広く使われるビルドツールで、開発中は手元でサーバーを起動し、ブラウザーに変更を即時に反映します。このサーバーは、ソースコードや設定ファイルがある開発者の端末で動くのが普通です。外部公開を前提にした本番のWebサーバーほど厳しく守られていないことも多く、そのぶん侵入されたときの影響が大きくなります。

Viteの開発サーバーでは、server.fsの許可リストを回避して範囲外のファイルが読み出される脆弱性が、過去にも修正されています。今回の脆弱性は、その許可リストの検査が、生成されたモジュールの中身を信頼していることに付け込む点が特徴です。ファイルの読み出しにとどまらず、evalを通じたコード実行にもつながります。

よくある質問

Q.本番環境に配信しているサイトも影響を受けますか。
A.アドバイザリが影響を受ける条件に挙げているのは、開発サーバーをネットワークに公開しているアプリです。vite buildで作った成果物を配信しているだけの環境は、この条件に入っていません。ただし、開発サーバーを本番に近い環境で動かしている場合は、条件に当てはまるので更新してください。
Q.`localhost`だけで使っている開発者は、更新しなくてよいですか。
A.アドバイザリが挙げる条件は、ネットワークへの明示的な公開です。localhostのみで使っているなら該当しないと読めますが、同じvite.configをチームやコンテナで共有していることもあるので、公開設定が紛れていないかを確認し、あわせて修正版へ更新しておくと安心です。

まだ分かっていないこと

  • 実際の攻撃で悪用されたかどうかは、アドバイザリに記載がありません。
  • 影響を受ける版の下限と、6.4系より古い系列で修正版が出るかどうかは、本文に記載がありません。

この記事は、取得元の公開情報をもとに、人が監修しながらAIを活用して執筆しています。執筆と監修は佐々木 航が担い、公開したあとも人が内容を確認しています。誤りに気づいたときは直し、記事の末尾に訂正の行を残します。対応を決める前に、下の原文と参照先も確認してください。

影響パッケージ

パッケージ影響を受ける版 → 修正版
npmvite
>=8.3.0,<=8.3.6→ 8.3.7
npmvite
>=8.2.0,<=8.2.4→ 8.2.5
npmvite
>=8.0.0,<=8.1.6→ 8.1.7
npmvite
>=7.0.0,<=7.3.7→ 7.3.8
npmvite
>= 4.0.0,<=6.4.5→ 6.4.6
npmvite-plus
<=1.5.0→ 1.5.1
原文の説明 取得元が公開している説明をそのまま載せています (多くは英語)。

Summary

By sending an HTTP request to the dev server, a arbitrary code execution was possible.

Impact

Only apps that match the following condition are affected:

Details

Vite's resolver plugin has __vite-browser-external: virtual module and __vite-optional-peer-dep: virtual module. These modules embedded the module ID, which is derived from the URL, without escaping. The `` can be any value, so any code was able to be injected in those modules.

Since Vite trusts the module code, there was two problems with this injection.

First, the modules referenced by a module are allowed for the server.fs check. For example, if the attacker injects import '/path/to/some-secret-file.txt', /path/to/some-secret-file.txt can be fetched.

Second, Vite uses eval to extract the value in the module code for new Worker and import.meta.glob. By using that functionality, the attacker can make Vite evaluate the injected code on the server. Vite prevents some module / global variables like exports, require to avoid bugs, but because this is not a security boundary, there's a bypass like globalThis.process.getBuiltinModule.

PoC

printf 'CANARY-SECRET-not-valid-js\n' > /tmp/decoy-secret.txt   # outside the project
vite

/tmp/decoy-secret.txt stands in for any sensitive file outside the…

出典: GitHub Repository Security Advisories (Game のスタック) GitHub Advisory OSV

参照URL

当サイトでは、アクセス解析と広告の効果測定のために Cookie を使います。株式会社Game のサイト共通の設定です。 詳しく