目次
メールアドレスや検索条件の検査は小さな処理に見えます。しかし、正規表現の組み方と入力の組み合わせによっては、照合が終わるまでの処理量が急激に増える場合があります。入力チェックを増やした結果、普通の利用者の要求まで止まる事態を避ける必要があります。
本記事は2026年10月18日にNode.jsの公式資料を確認した実務解説で、特定の障害や攻撃の速報ではありません。試験と改修の順序は本サイトの提案です。正規表現のエンジンごとに挙動が異なるため、一般的な形の指摘だけで脆弱性の有無を断定しません。
スポンサーリンク
問題は正しい入力より失敗する入力で見つかる
一部のエンジンは、照合に失敗すると別の分割や選択肢を試し直します。重なった繰り返しや曖昧な選択があると、この戻りが多くなる場合があります。短い正常値だけの試験では、最後の部分だけ合わない長い入力の処理量を見落とします。
Node.jsの公式資料は、危険な正規表現がイベントループを塞ぐ問題を説明しています。ただし、繰り返しがある式はすべて危険、特定の見た目なら必ず指数的になる、とまではいえません。実際に使うエンジンと式、入力の上限を組み合わせて判断します。
照合が重い原因が常にReDoSとも限りません。大量の単純な照合、巨大な入力、複数回の変換、別の同期処理が原因になる場合もあります。要求全体のどこで時間を使うかを測定します。
出典:Node.js Don't Block the Event Loop。
自作の入力検査だけを調べない
本サイトの提案は、外部の値に触る正規表現を入口ごとに棚卸しすることです。フォーム、検索、URLの処理、アップロードした文書、ログの整形、外部サービスの回答を含めます。ログイン前の機能だけでなく、利用者が長い値を保存して後から処理させる経路も対象です。
設定画面で正規表現そのものを登録できる機能は、値だけを受け付ける機能より広い能力を渡します。管理者向けでも、必要な機能か、誰が登録できるか、どの量を照合するかを定義します。管理者の誤設定が全体へ波及する場合もあります。
ライブラリー内部の正規表現も無関係ではありません。依存関係の更新と注意喚起を確認し、処理対象の上限をアプリ側でも決めます。自作の式だけを消したから対策完了、とは判断しないでください。
スポンサーリンク
長さを制限する段階を先に決める
重い照合へ入る前に、業務で必要な入力の最大量を決めます。長さを測る単位が文字数なのかバイト数なのかも明示します。読み込み後に長さを調べるだけでは、読み込みや展開の時点の資源消費は制限できません。
HTTPの上限、デコード後の上限、個々の項目の上限を対応させます。圧縮や文字変換で量が変わる構成では、変換後も想定内かを確認します。検索語のような短い値と、文書本文のような長い値を同じ上限で扱わないようにします。
上限を設けた後も、その範囲内で処理が終わるかを測定します。非常に重い式を残したまま、何となく大きな上限を付けるだけでは、実際の応答時間に合う保証はありません。
複雑な照合を業務の条件へ分解する
部分文字列の有無や固定の接頭部を調べるだけなら、単純な文字列の操作で十分な場合があります。構造を持つ形式は、その形式に合う解析器を使う方が、巨大な正規表現へ条件を詰め込むより意図が伝わることがあります。
正規表現を残す場合は、曖昧な繰り返しや選択を減らし、何に一致させる必要があるかを明確にします。先頭と末尾を指定したから、あらゆる戻りがなくなるわけではありません。高速そうな書き換えで正常値の判定が変わらないかも確認します。
本サイトの提案は、まず許す入力の仕様を例で固定してから式を変更する手順です。正しい値、境界の値、拒否すべき値を分け、性能と判定の両方を評価します。安全のために業務上必要な値まで黙って落とさないようにします。
スポンサーリンク
タイマーだけでは同期処理を止められない
Node.jsで同期の正規表現がイベントループを占有している場合、同じイベントループのタイマーは、予定した瞬間にその処理を割り込んで止めるものではありません。Promiseで包むだけでも、元の同期処理が別の場所へ移るわけではありません。
本サイトの提案として、実行時間の上限が必要な処理は、基盤が実際に中断できる仕組みを使って設計します。別ワーカーや別プロセスを使う場合も、同時数、待ち行列、終了方法を限定し、無制限に新しい処理を作らないようにします。
分離は、入力上限や式の改善の代わりではありません。重い処理を別の場所へ送るだけでは、CPUやメモリーの全体量を使い切る場合があります。正常な機能のために残す資源と、失敗時の応答を決めることが必要です。
別のエンジンへ変えるときは互換性を確認する
戻り探索に依存しないエンジンを検討する方法もあります。Node.jsの資料はRE2系の選択肢と、V8の正規表現との互換性の差へ言及しています。使っている構文や一致の結果を確かめず、そのまま置き換えられると考えないでください。
必要な機能を整理し、サポートしない構文がある場合は仕様を変えられるかを判断します。導入先のOS、実行環境、配布方法、依存関係の更新責任も含めて確認します。別のエンジンを入れたことだけを、要求全体の処理量の保証にしないようにします。
静的な検査ツールは、危険な候補を探す助けになりますが、見逃しや誤検知を考慮します。ツールが通ったことと、現在の入力上限で実測したことは別の証拠として扱います。
失敗する条件を小さく段階的に試す
本番へ巨大な入力を送る試験ではなく、隔離した環境で入力の長さを少しずつ増やします。正常に一致する場合と、よく似ているが最後に失敗する場合を用意し、経過時間と資源消費を比較します。試験自体の中断条件も先に決めます。
時間だけでなく、同時に走る通常の要求が遅くなるかを見ます。試験環境と本番でCPUやエンジンの版が異なる場合、その差を記録し、測定結果を無条件に本番の保証へ読み替えないようにします。
修正後は、処理時間が抑えられたことと、正常な値を引き続き受け付けることを照合します。安全な上限を超える値には、実行を始める前に分かりやすい拒否を返す設計にします。
一件の上限と同時の上限を分ける
一つの照合が許容時間内でも、多数の要求が同じ処理を使えば、全体の資源を使い切る場合があります。本サイトの提案は、一件の最大量と同時に処理する件数、待ち行列の長さを分けて設計することです。読み込みの入口で制限したつもりでも、別のAPIやバッチから同じ重い処理を呼べる場合があります。
利用者ごとの制限だけでは、匿名の入口や複数のアカウントを使う条件を扱えません。正規の利用を妨げない範囲で、処理全体に使う資源の上限も検討します。上限に達した後、すぐ拒否するか、待たせるかを機能ごとに決めます。
通知やログの整形で正規表現を使う場合は、失敗した値の記録が再び同じ式へ入り続けないことも確認します。観測のための処理まで重くなると、原因を調べる手段が失われる場合があります。
スポンサーリンク
許容時間を変更前に定義する
仮想の検索フォームで、短い語句を判定する処理と、長い文章を解析する処理を考えます。同じ式と同じ時間枠で扱うのではなく、利用者が待てる時間と、サイトが残すべき資源から目標を決めます。対策後の式が以前より速いだけではなく、その目標の中で動くかを確認します。
測定では平均だけでなく、長くかかった条件を確認します。データの長さ、文字の種類、一致と不一致の別、エンジンの版を記録しておくと、将来の更新で差が出た理由を追いやすくなります。実測値を公開する場合は、測定した環境と条件を添え、別の環境での性能を保証しないようにします。
実運用へ出した後も、入力の上限と業務仕様が一緒に変更される仕組みを用意します。機能追加で最大長だけを広げる変更が、性能の前提を崩さないかをレビューすることが大切です。
中断後の結果を曖昧にしない
時間の上限で処理を止めたとき、それを入力が正しいとみなす救済処理は避けます。反対に、不正な値と確定できていないのに、利用者を攻撃者として扱う必要もありません。検証を完了できなかった結果として、再操作や別の方法を案内する設計を検討します。
ワーカーを停止する構成では、途中のファイルや保存状態が残らないかも確認します。正規表現の性能を改善する作業であっても、周囲の処理が中断へ耐えられることを確かめる必要があります。
スポンサーリンク
監視は全文の保存より遅延の位置を捉える
監視する候補は、入口ごとの遅延、上限超過、処理の中断、ワーカーの待ち行列などです。Node.jsなら、イベントループの遅れが他の要求へ波及していないかも観察します。必要な指標は実際の構成に合わせて選びます。
問題の入力全文を常に記録すると、個人情報や秘密をログへ移してしまいます。入力の長さ、処理の種類、安全な相関IDなどで追えるようにし、詳細な再現用データはアクセスを限定して管理します。
ReDoS対策は、式の形だけを採点する作業ではありません。どの入力をどの量まで処理し、いつ諦め、他の機能に何を残すかを決める作業です。入口の制限、処理の単純化、検証と監視を組み合わせて進めてください。
参考資料
以下の一次資料を2026年10月18日に確認しました。本文の仮想例と運用手順の提案は、資料の引用とは区別しています。









