FlawOpen

flawopen.com/ReDoS/JavaScript RegExp

JavaScript RegExpはReDoSに弱い?

CWE-1333: Inefficient Regular Expression Complexityリファレンスページ
要点

最後の印がない書類の束を、担当者があらゆる方法で分割し直す状況を想像してください。曖昧なパターンは正規表現エンジンに同じ文字を何度も調べさせます。V8で通常使われるRegExp経路はこのようにバックトラックすることがあります。入力を制限し、処理量が予測できるパターンにすれば負荷を抑えられます。Nodeでは同期的な照合がevent loopのスレッド上で動き、時間がかかると同じプロセスの他のcallbackを遅らせます。 V8はフラグで有効化する実験的な非バックトラッキングエンジンを説明していますが、パターンに制約があります。本番Nodeで有効とは限りません。

脆弱な例
// リクエストデータに曖昧な入れ子反復を適用
const re = /^(\w+\s?)*$/;

app.post('/search', (req, res) => {
  const q = req.body.q;
  if (!re.test(q)) return res.sendStatus(400);
  res.sendStatus(200);
});
修正版
// 入力を制限し、フィールド文法のみ許可
app.post('/search', (req, res) => {
  const q = req.body.q;
  if (typeof q !== 'string' || q.length > 128)
    return res.sendStatus(400);

  // 例:ASCIIの単語文字と空白のみ
  if (!/^[\w ]{1,128}$/.test(q))
    return res.sendStatus(400);

  res.sendStatus(200);
});

Node.jsがReDoSの影響を増幅する理由

同期的な正規表現照合は、Node.jsプロセスのcallbackを処理するJavaScriptスレッドで実行されます。パターンが近似一致や不一致の入力で長時間かかると、照合が返るまでevent loopは他のcallbackを実行できず、リクエストも進みません。Worker、複数プロセス、レプリカで一部の容量を保てる場合もありますが、影響を受けた各プロセスは停止します。

影響は到達可能性、パターンの複雑さ、入力制限、構成に左右されます。攻撃者が高コストの経路を起動する入力を脆弱な照合に到達させる必要があります。影響を受けたプロセスの可用性リスクとして扱い、サービス全体への影響はworker、レプリカ、ルーティング、ヘルスチェックを含めて判断してください。

npmの実例:xmldomのCVE-2026-83606

@xmldom/xmldomの審査済みアドバイザリは、処理命令の解析にCWE-1333を報告しています。脆弱な文法では貪欲な空白グループと遅延データグループが同じ空白を消費します。閉じる?>がないと、parserは多数の分割を試し、計算量は二次になります。0.9.0-beta.9から0.9.10が影響を受け、0.9.11では区切りが空白をデータグループへ戻せないよう修正されました。対象はscope付きパッケージの0.9.x経路で、0.8.xとscopeなしのパッケージは影響対象として挙げられていません。

依存関係スキャンは役立つが、正規表現の安全証明ではない

npm auditは依存ツリーに一致する既知のアドバイザリを報告しますが、ソース内の全正規表現を分析したり、未公開のReDoSを発見したりはしません。直接・間接依存を更新し、影響する呼び出し経路を確認し、ユーザー入力を処理するパターンも別途点検してください。

npm audit --omit=dev

auditは既知のアドバイザリを対象とし、すべての正規表現リスクを検出しません。デプロイ環境に合わせてレポートを確認し、信頼できない入力が高コスト照合に届くか、長さ制限があるかを別途確認してください。

よくある質問

JavaScript正規表現にタイムアウトを設定できる?

RegExp APIに照合ごとのタイムアウトはありません。単純なパターンを使い、照合前に入力を制限します。複雑な照合が必要なら、強制終了期限を設けたWorkerまたは子プロセスに隔離します。影響は抑えられますが、パターン自体が効率化するわけではありません。

ブラウザーのJavaScriptにも影響する?

はい。問題のある同期照合は、終了するまでページのメインスレッドを固め、UIを止めることがあります。入力を制限し、パターンを単純化して、キー入力ごとの重い照合を避けてください。

検索にnew RegExp(userInput)を使っても安全?

ユーザー提供パターンは高コストなmatcherに渡す実行入力として扱います。厳格な制限と隔離なしにサーバーで任意のパターンを受け付けないでください。文字列そのものを検索するだけなら、入力を正規表現リテラルとしてescapeするか文字列検索APIを使います。escapeだけでは長さ制限の代わりになりません。

参考資料と修正

関連項目 ReDoS(壊滅的バックトラッキング)とは?