Modern Frontend CVEs

対象CVE: CVE-2026-14257

[緊急警告] Node.jsプロセスを停止させる!brace-expansionのDoS脆弱性 (CVE-2026-14257) を解説

npmパッケージの依存関係で広く利用されている`brace-expansion`ライブラリに、Node.jsプロセスを強制終了させるサービス拒否 (DoS) 脆弱性 (CVE-2026-14257) が発見されました。フロントエンドのビルドツールや開発サーバーなど、Node.jsベースの環境に深刻な影響を及ぼす可能性があります。

はじめに:深刻なDoS脆弱性がNode.jsプロセスを狙う

フロントエンド開発者の皆さん、こんにちは。今回は、Node.js環境で広く利用されている`brace-expansion`というnpmパッケージに発見された、深刻なサービス拒否(DoS)脆弱性(CVE-2026-14257、GHSA-mh99-v99m-4gvg)について解説します。この脆弱性は、特定の悪意ある入力によってNode.jsプロセス全体をクラッシュさせ、サービスを停止させる可能性があります。

直接`brace-expansion`を利用していなくても、`minimatch`や`glob`といったファイルパスのパターンマッチングライブラリを通じて間接的に利用されているケースが多く、皆さんの開発・デプロイ環境に影響を及ぼす可能性があります。

`brace-expansion`とは?そして何が問題なのか

`brace-expansion`は、`{a,b}c{d,e}`のようなブレース展開パターン(bashのブレース展開に似た機能)を文字列に展開するためのライブラリです。例えば`{a,b}c`は`ac`, `bc`に展開されます。

このライブラリの`expand()`関数には、生成する結果の**数**を制限する`max`オプション(デフォルト100,000)がありますが、生成される個々の文字列の**長さ**には制限がありませんでした。

攻撃者は、`'{a,b}'.repeat(N)`のように多数のブレースグループを連結した文字列を入力として与えることで、結果の数を`max`の範囲内に保ちつつ、各結果文字列の長さを指数関数的に増大させることができます。

脆弱性のメカニズム:なぜOOMクラッシュが発生するのか

例えば`'{a,b}'.repeat(1500)`という約7.5KBの短い入力文字列を考えてみましょう。この入力に対して`expand()`が処理を行うと、以下のようなメカニズムでメモリが逼迫します。

1. **結果文字列の長さが無限に増大:** `N`個のブレースグループがある場合、生成される各文字列は`N`文字の長さになります。`max`オプションによって結果の「数」は制限されますが、個々の文字列が長大になることを防げません。

2. **中間配列とCons-stringによるメモリ消費:** `brace-expansion`の内部では、`expand_`関数が再帰的に呼び出され、各段階で中間的な文字列配列が生成されます。V8エンジンは文字列連結をCons-string(ロープ)として効率的に扱いますが、このケースでは中間文字列が長く、大量に生成されるため、それらへの参照が保持され、メモリが解放されにくくなります。

3. **Node.jsプロセスの強制終了:** 結果として、`max × N`に比例する膨大なメモリが消費され、Node.jsプロセスはJavaScriptヒープのメモリ不足(Out-Of-Memory, OOM)により、「`FATAL ERROR: ... JavaScript heap out of memory`」という致命的なエラーでクラッシュします。

4. **`try/catch`では防げない:** このOOMエラーはJavaScriptの例外として捕捉できない(uncatchable)ため、`try/catch`ブロックで`expand()`を囲んだとしても、プロセス自体が停止してしまいます。これはサービス運用において極めて危険です。

具体的な影響とProof of Concept (PoC)

この脆弱性は、ユーザーからの入力(例:CLIツール、設定ファイル、APIリクエストのパスパターンなど)を`brace-expansion`が処理するようなアプリケーションで影響を受けます。特に、`minimatch`や`glob`といったライブラリを介して間接的に`brace-expansion`を利用している場合でも危険です。

例えば、フロントエンドのビルドツール(Webpack, Rollup, Viteなど)がファイルパスのパターンマッチングに`glob`系のライブラリを使用している場合、悪意のあるパターンが入力されるとビルドプロセスが停止する可能性があります。開発サーバーやCI/CDパイプラインも同様です。

以下のPoCコードは、Node.jsプロセスを強制終了させます。

```javascript const { expand } = require('brace-expansion'); // 約7.5KBの入力で、致命的なメモリ不足によりプロセスがクラッシュします try { expand('{a,b}'.repeat(1500)); } catch (e) { // このブロックには到達しません - プロセスはすでに終了しています console.error("エラーを捕捉しました:", e); } console.log("このメッセージは表示されません。"); ```

対策:速やかにバージョンアップを!

この脆弱性への最も効果的な対策は、`brace-expansion`を修正済みのバージョンにアップグレードすることです。

**修正内容:** パッチでは、単一の`expand()`呼び出しで蓄積される合計文字数に`maxLength`という新しい制限(デフォルト4,000,000文字)が導入されました。この制限は出力生成ループの内部で適用され、中間配列のサイズも適切に制限されます。制限に達すると出力は途中で打ち切られ、メモリが無制限に増大することはありません。

この`maxLength`は、正当な用途でのブレース展開には影響を与えないように十分高い値に設定されています。

**バージョンアップが不可能な場合の回避策:** * 信頼できない入力を`expand()`や`glob`のブレースパターンに渡さない。 * `expand()`関数に、明示的に`max`オプションと新しい`maxLength`オプション(もし利用可能であれば)を小さい値で指定する。

まとめ

`brace-expansion`のDoS脆弱性 (CVE-2026-14257) は、Node.jsプロセスを完全に停止させる可能性があるため、非常に危険です。フロントエンド開発者は、自身のプロジェクトがこのライブラリを直接的または間接的に利用していないか確認し、速やかに修正済みのバージョンへのアップグレードを強く推奨します。

依存関係ツリーを確認し、安全な環境を維持するように努めましょう。

← ブログ一覧に戻る