Modern Frontend CVEs

対象CVE: CVE-2026-92950

[High] vm2 CLIのサンドボックスが機能しない脆弱性 (CVE-2026-92950) を解説

Node.jsのサンドボックスライブラリ`vm2`のCLIツールに、サンドボックスを完全にバイパスし、ホスト環境で任意のコードが実行されてしまう深刻な脆弱性(CVE-2026-92950)が発見されました。CLI経由で信頼できないスクリプトを実行している開発者は特に注意が必要です。

どんな脆弱性?:`vm2` CLIにおけるサンドボックスの完全な崩壊

今回注目するのは、Node.jsでセキュアなコード実行環境(サンドボックス)を提供する人気ライブラリ`vm2`のCLIツールに見つかった、深刻度「High」の脆弱性 (GHSA-jxxv-8r27-vm4p / CVE-2026-92950) です。

`vm2` CLI (`vm2 <file>`) を使用して信頼できないスクリプトを実行すると、そのスクリプトが`vm2`のサンドボックスを完全にバイパスし、ホストNode.jsプロセス上で任意のコードを実行できてしまうというものです。これにより、ファイルシステムの読み書き、子プロセスの実行、ネットワーク通信など、ホストOSが許す限りの操作が可能になります。これは、サンドボックスを導入する目的を根底から覆す極めて危険な状態と言えます。

`vm2`とは?:Node.jsにおけるサンドボックスの提供

フロントエンド開発では、ユーザーが記述したコードや信頼できないサードパーティのスクリプトを安全に実行する必要がある場面が少なからず存在します。例えば、オンラインエディタでのコードプレビュー、プラグインシステムの提供、Linterやビルドツールでのコード解析などが挙げられます。`vm2`は、このようなシナリオにおいて、Node.jsのV8仮想マシン上で隔離された環境(サンドボックス)を提供し、外部からの不正なアクセスや悪意あるコードの実行を防ぐことを目的としたライブラリです。

通常、`vm2`を使用することで、サンドボックス内で実行されるコードは`fs` (ファイルシステム) や `child_process` (子プロセス) といったNode.jsの組み込みモジュールに直接アクセスできなくなり、安全性が保たれます。

具体的な脆弱性の内容:ホストの`require()`が呼び出される

この脆弱性は、`npm install -g vm2` でインストールされる`vm2`のCLIツール(`bin/vm2`または`vm2`コマンド)に存在します。CLIは、引数として渡されたスクリプトを`NodeVM.file()`メソッドを使って実行します。この際、`require:{external:true}`オプションは設定されますが、重要な`root`、`context`、`builtin`といったオプションは未設定のままです。

これが問題の核心です。`vm2`の内部的なモジュールリゾルバーは、`require.root`が設定されていない場合、すべてのファイルシステムパスへのアクセスを許可してしまいます。そして、`require()`の解決パスがホスト環境と判断されると、サンドボックスを介さずに、**ホストNode.jsプロセスの実際の`require()`関数が呼び出されてしまう**のです。

結果として、サンドボックス内で`require(__filename)`のように自分自身を再度requireするような悪意のあるコードを実行すると、そのモジュールの本体がサンドボックスの外側、つまりホストNode.jsプロセス上で実行されてしまいます。これにより、サンドボックスによって隔離されるはずの`fs`や`child_process`といったモジュールにもアクセスできるようになります。

なぜこんなことが起こったのか?:デフォルト設定の落とし穴

脆弱性の詳細は以下の技術的な経路をたどります:

1. `vm2` CLIは、`NodeVM.file(path, { verbose: true, require: { external: true } })` を呼び出します。ここで`require.root`や`context`が指定されていません。

2. 内部のリゾルバー(`lib/resolver-compat.js`)において、`require.root`が`undefined`であるため、`isPathAllowed(filename)`メソッドが常に`true`を返します。これにより、すべてのファイルシステムパスがサンドボックスからアクセス可能と見なされます。

3. モジュールのロード処理(`loadJS`メソッド)において、ファイルパスのコンテキストが`'host'`と判断された場合、`this.hostRequire(filename)`が呼び出されます。この`hostRequire`は、他ならぬ**Node.jsホスト環境の実際の`require()`関数**そのものです。

4. 結果として、悪意あるスクリプトのモジュール本体は、サンドボックスの制限を受けることなく、ホストOS上で実行されてしまいます。これにより、例えば`fs.writeFileSync()`のような危険な操作も可能になります。`vm.readonly()`によるエクスポートのラップは、サイドエフェクトが発生した後に行われるため、手遅れとなります。

影響範囲とリスク:ホスト環境の乗っ取り

この脆弱性が悪用された場合、以下のような深刻な影響が考えられます。

私たちフロントエンドエンジニアは何をすべきか?(対策)

この脆弱性は非常に深刻であり、速やかな対応が求められます。特に以下の点に注意してください。

まとめ

`vm2`のCLIツールにおけるサンドボックスバイパス脆弱性 (CVE-2026-92950) は、サンドボックスの目的を完全に無効化する、極めて危険な問題です。`vm2` CLIを使用している場合は、直ちにその利用を停止し、安全な代替策を講じる必要があります。また、ライブラリとして`vm2`を使用している場合も、セキュリティオプションの適切な設定が不可欠であることを再確認する良い機会となります。

セキュリティは常に進化する脅威との戦いです。最新の脆弱性情報をキャッチアップし、ご自身のプロジェクトのセキュリティを常に意識していくことが、私たちフロントエンドエンジニアにとっても重要な責務と言えるでしょう。

← ブログ一覧に戻る