Modern Frontend CVEs

対象CVE: CVE-2026-92939

[緊急解説] vm2のCriticalなサンドボックスエスケープ脆弱性 (CVE-2026-92939) と対応策

vm2の旧バージョンに、`crypto`モジュール経由でホストOSを乗っ取られるCriticalな脆弱性 (CVE-2026-92939) が発見されました。信頼できないコードを実行しているシステムは、緊急にvm2を最新版にアップデートし、`crypto`モジュールの使用設定を見直す必要があります。

はじめに:なぜフロントエンドエンジニアも知るべきなのか

`vm2`は、Node.js環境で信頼できないコードを安全に実行するためのサンドボックスライブラリです。プラグインシステム、サーバーサイドレンダリング (SSR)、CLIツール、各種ビルドツールなど、Node.jsベースの様々な環境で利用される可能性があります。バックエンド寄りの技術と思われがちですが、Node.jsを深く利用するフロントエンド開発においても、その安全性は極めて重要です。

今回解説する脆弱性 (GHSA-46pr-c5wc-xffx / CVE-2026-92939) は、`vm2`のサンドボックスが完全に突破され、ホストOS上で任意のコードが実行されるという極めて深刻なものです。あなたの開発環境や本番環境で`vm2`が使われている可能性があるため、必ず内容を理解し、適切な対応を取ってください。

脆弱性の概要:`crypto`モジュールが引き起こす致命的な穴

`vm2`のバージョン3.11.6以前において、`NodeVM`インスタンスで`crypto`モジュールを許可している場合に、サンドボックスを完全に突破し、ホストOS上で任意のネイティブコード(C言語などで書かれた低レベルなプログラム)が実行されてしまう脆弱性が発見されました。これは、サンドボックス内で実行されるコードが、Node.jsプロセスと同等の権限でホストシステムを操作できることを意味します。

特に注目すべきは、この攻撃に通常サンドボックスエスケープに必要とされる`fs`(ファイルシステムアクセス)や`process`(プロセス制御)といった危険なモジュールが一切不要である点です。`crypto`モジュールだけが許可されていれば攻撃が成立するため、影響範囲が広範にわたります。

具体的な攻撃メカニズム:`crypto.setEngine()`の悪用

この脆弱性の根源は、Node.jsの`crypto`モジュールが提供する`crypto.setEngine()`関数にあります。この関数は、OpenSSLに対して、指定されたファイルパスにあるネイティブライブラリを動的にロードさせる機能を持っています。

攻撃者は、悪意のあるネイティブライブラリ(例: 危険な処理を記述した共有ライブラリファイル)を自身のnpmパッケージなどに含めておき、サンドボックス内で実行されるJavaScriptコードから`crypto.setEngine()`を呼び出して、この悪意あるライブラリをホストプロセスにロードさせます。

OSのダイナミックローダーは、ネイティブライブラリをロードする際に、そのライブラリのコンストラクタ(初期化処理)を、OpenSSLがライブラリの正当性を検証するよりも早く実行してしまう特性があります。このタイミングのずれが悪用され、OpenSSLが不正なライブラリと判断してエラーを発生させたとしても、既に悪意のあるネイティブコードがホスト上で実行されてしまう、という流れで攻撃が成功します。

攻撃が成立する条件と深刻な影響

この攻撃は、`NodeVM`インスタンスで`crypto`モジュールが許可されている場合にのみ成立します。しかし、前述の通り、`fs`や`process`といったモジュールが禁止されていても、`crypto`モジュールだけが許可されていれば攻撃が可能です。

この脆弱性が悪用されると、攻撃者はサンドボックスを完全に突破し、Node.jsホストプロセスの権限で任意のネイティブコードを実行できます。これにより、以下のような極めて深刻な被害が発生する可能性があります。

* **機密情報の窃取**: アプリケーションの秘密鍵、環境変数、認証情報、ホスト上の重要ファイルなど、あらゆる機密情報にアクセスされます。 * **データ改ざん・バックドア**: アプリケーションのデータが改ざんされたり、永続的なバックドアが確立され、将来的な再攻撃の足がかりにされたりする可能性があります。 * **内部システムへの侵入**: ホストのネットワークIDを利用して、通常アクセスできない内部サービスやデータベースなどへアクセスされる危険性があります。 * **他ユーザーデータへのアクセス**: マルチテナント環境の場合、同じプロセス内で動作する他ユーザーのデータが窃取される可能性があります。 * **サービス停止・破壊**: ホストプロセスの停止や破損を引き起こし、サービスの可用性に甚大な影響を与える可能性があります。 * **OSレベルの操作**: ホストアカウントに許可された任意のOS操作(例: 新しいユーザーの作成、ファイルの削除、マルウェアのインストール)が可能になります。

緊急対応!今すぐ実行すべき対策

この脆弱性はCriticalな深刻度であり、速やかな対応が求められます。

1. **最優先で`vm2`を最新バージョンにアップデートしてください。** `vm2`の脆弱性が修正されたバージョンに更新することで、このリスクを回避できます。プロジェクトの依存関係を確認し、`package.json`の`vm2`を更新し、`npm install`または`yarn install`を実行してください。 ``` # package.jsonのdependenciesでvm2を更新 # 例: "vm2": "^3.11.6" を "vm2": "^3.11.7" 以上に npm update vm2 # または yarn upgrade vm2 ```

2. **`NodeVM`で`crypto`モジュールを許可しないように設定を見直してください。** 信頼できないコードを`NodeVM`で実行する際、`crypto`モジュールを許可する必要があるかどうかを厳しく再評価してください。特に、外部から提供されるプラグインやスクリプトをサンドボックス内で実行し、`crypto`モジュールを許可しているシステムは、早急な設定変更が必要です。 ```javascript // 脆弱な設定例 (cryptoモジュールが許可されている) const { NodeVM } = require('vm2'); const vm = new NodeVM({ console: 'inherit', require: { external: true, builtin: ['crypto', 'path'], // ここで'crypto'が許可されている root: './' } }); // 安全な設定例 (cryptoモジュールを許可しない) const vmSafe = new NodeVM({ console: 'inherit', require: { external: true, builtin: ['path'], // 'crypto'を削除 root: './' } }); // または、必要な場合のみ許可するモジュールを最小限に絞る // 明示的にbuiltin: ['crypto'] としない限り、デフォルトでは許可されない const vmMinimal = new NodeVM({ console: 'inherit', require: { external: true, builtin: ['path'], // 必要なモジュールのみをリスト context: 'sandbox' } }); ``` もし`crypto`モジュールを許可する必要がある場合は、実行するコードの信頼性を徹底的に検証するか、より安全な代替手段(例えば、`crypto`処理を別の安全なマイクロサービスに分離するなど)を検討してください。

まとめ

`vm2`のCriticalなサンドボックスエスケープ脆弱性について解説しました。この脆弱性は、`crypto`モジュールという一見無害に見える機能が悪用されることで、ホストOSが完全に乗っ取られる危険性があります。

フロントエンドエンジニアの皆さんにとって、Node.js環境のセキュリティは開発ツールのサプライチェーンやサーバーサイドでの動作に直結します。速やかに`vm2`のバージョンアップと設定の見直しを行い、安全な開発・運用環境を維持しましょう。

← ブログ一覧に戻る