Modern Frontend CVEs

対象CVE: CVE-2026-92944

[緊急警告] Node.js 26とvm2にCriticalなサンドボックスエスケープ脆弱性 - フロントエンド開発者への影響と対策

Node.js 26環境でサンドボックスライブラリvm2を使用している場合に、ホストOSを乗っ取られる可能性のあるCriticalな脆弱性(CVE-2026-92944)が発見されました。Node.jsを使ったバックエンド処理やビルドツールにvm2を利用しているフロントエンド開発者は、直ちに対策を検討する必要があります。

はじめに:Node.js 26とvm2利用のフロントエンド開発者へ緊急警告

フロントエンド開発の現場では、Node.js環境で様々なツールやスクリプトが動作しています。特にサンドボックス環境を提供する`vm2`のようなライブラリは、信頼できないコードを実行する際にセキュリティを確保するために重要です。しかし、この度`vm2`にNode.js 26環境下でサンドボックスを完全に突破されるCriticalな脆弱性(CVE-2026-92944 / GHSA-27g9-p43v-cw3v)が発見されました。これはホストOS上で任意のコードが実行される可能性を秘めており、Node.jsを利用しているすべての開発者にとって無視できない問題です。

脆弱性の概要:サンドボックスが機能しない危険性

この脆弱性は、`vm2`のバージョン3.10.2から3.11.5までを、Node.js 26(または一部の27系の初期ナイトリービルド)で利用している場合に発生します。悪意のあるJavaScriptコードが`vm2`のサンドボックス内で実行されると、その制限を完全に回避し、ホストOS上で任意のコマンド実行が可能になります。これは、ビルドサーバー、CI/CD環境、またはユーザー提供コードを処理するバックエンドなど、Node.jsを使用するあらゆる環境で深刻な影響を及ぼす可能性があります。具体的には、機密情報の窃取、システムの破壊、他のサーバーへの攻撃などに悪用される恐れがあります。

なぜサンドボックスが破られるのか?技術的な詳細

通常、`vm2`はサンドボックス内のコードがホスト環境にアクセスできないよう、`Promise.prototype.then`や`catch`といったJavaScriptの組み込みメソッドを、独自の安全なラッパーで置き換えます。しかし、Node.js 26が採用しているV8エンジン(バージョン14.6)の内部的な挙動に問題がありました。

V8エンジンの最適化処理が、`Promise.prototype.then`などを更新する際に、`PromiseThenLookupChain`というPromiseの保護機構を正しく無効化しないため、`Promise.prototype.finally()`が呼び出されると、V8は保護機構が有効だと誤解します。結果として、`vm2`が設定したラッパーが迂回され、ネイティブな`then`メソッドが直接呼び出されてしまいます。

この迂回により、攻撃者は`constructor[Symbol.species]`を悪用し、ネイティブなPromiseの処理中に意図的にスタックオーバーフローを引き起こします。これにより、ホスト環境の`RangeError`エラーオブジェクトを直接取得し、そのプロトタイプチェーンを辿ってホストの`Function`コンストラクターや`process`オブジェクトにアクセス。最終的にホストOS上で任意のコード実行を可能にするという非常に巧妙な攻撃です。

影響を受ける条件と確認方法

ご自身のプロジェクトが以下の条件に該当するか確認してください。

<ul><li><strong>vm2のバージョン:</strong> 3.10.2から3.11.5までの全バージョン、および現在の`main`ブランチ。</li><li><strong>Node.jsのバージョン:</strong> Node.js 26系のすべてのバージョン(26.0.0から26.7.0)。Node.js 25以前、またはV8バージョン15.3.55以降を搭載したNode.js 27以降は安全とされています。</li><li><strong>vm2の設定:</strong> デフォルトの`new VM()`、または`allowAsync: true`などより厳しい設定でも影響を受けます。`async`関数のサポートが有効であること(vm2のデフォルト設定)。WebAssembly、動的な`eval`、ホストオブジェクトの公開などは不要です。</li></ul>

これらの条件が揃っている場合、あなたの環境は本脆弱性の影響を受ける可能性があります。特に、ビルドプロセスでユーザー提供のスクリプトを実行したり、サーバーレス関数などで信頼できないコードを扱う場合に注意が必要です。

いますぐ取るべき対策

この脆弱性は非常に深刻であるため、以下のいずれかの対策を速やかに実行してください。

<ul><li><strong>1. vm2のアップデート:</strong> 修正版がリリースされ次第、`vm2`を最新バージョンにアップデートしてください。`vm2`開発チームは`Promise.prototype.then`および`catch`のラッパーを、`Reflect.defineProperty`や`Object.defineProperty`のようなより堅牢な方法でインストールするよう推奨されています。</li><li><strong>2. Node.js 26の使用回避:</strong> `vm2`の修正がリリースされるまでの間、可能であればNode.js 26の使用を避け、安全が確認されているNode.jsのバージョン(例:25以前、または修正版V8を含む27以降)への移行を強く推奨します。</li><li><strong>3. `Promise.prototype.finally()`のラッパー化 (暫定対策):</strong> `vm2`の修正がまだの場合は、`Promise.prototype.finally()`のエントリーポイント自体をラップし、ネイティブの`finally`を呼び出す前に`resetPromiseSpecies(this)`を実行するような暫定的な対策も検討されています。ただし、これは`vm2`内部の実装に依存するため、ライブラリのアップデートが最優先です。</li><li><strong>4. Node.jsへのV8修正のバックポート:</strong> Node.js開発チームと連携し、V8の関連する保護機構の修正がNode.js 26リリースラインにバックポートされるよう働きかける動きもあります。公式のアナウンスを注視してください。</li></ul>

まとめ:セキュリティは継続的な課題

この`vm2`の脆弱性は、一見安全に見えるサンドボックス環境でも、基盤となるV8エンジンの細かな挙動や、PromiseのようなJavaScriptのコア機能の相互作用によって、予期せぬ抜け穴が生じる可能性を示しています。フロントエンド開発者は、使用しているライブラリやランタイム環境のバージョン、そしてその依存関係に常に注意を払い、公式からのアナウンスを迅速に確認し、適切な対応を取ることが求められます。特に、`Node.js 26`と`vm2`を組み合わせている場合は、直ちに対策を講じてください。最新の情報にアクセスし、セキュリティパッチの適用を怠らないことが、安全な開発環境を維持する上で不可欠です。

← ブログ一覧に戻る