お使いのNode.jsはBrotliのRCE脆弱性の影響を受けるか?2分で確認

CVE-2026-111497は、Node.jsのBrotliデコーダーにおいて現在悪用が確認されている脆弱性です。2分でお使いのバージョンを確認し、どのフレームワークやHTTPクライアントがデコーダーを呼び出しているかを把握した上で、インストール方法に応じたパッチを適用してください。今すぐアップグレードできない場合の緩和策についても解説します。

Ashley Innocent

Ashley Innocent

5 11月 2026

お使いのNode.jsはBrotliのRCE脆弱性の影響を受けるか?2分で確認

Apidog エンタープライズ

オンプレミスデプロイ

SSO & RBAC

SOC 2 準拠

Apidog Enterpriseを見る

今すぐ実行してください。お使いのバージョンが以下の表の基準を下回っている場合、Node.jsのBrotli RCE(CVE-2026-111497)の影響を受けます。攻撃者による悪用もすでに始まっています。

node -v
リリースライン 影響を受けるバージョン 修正済みバージョン 最新版(2026年11月5日時点)
26.x 26.12.1 未満 26.12.1 26.13.0
24.x 24.22.1 未満 24.22.1 24.22.2
22.x 22.23.4 未満 22.23.4 22.23.4
25.x、20.x、それ以前 サポート終了(EOL):未パッチかつ未評価 修正パッチなし 24または26へ移行

もうひとつの確認方法として、バイナリに直接問い合わせることもできます。

node -p "require('node:zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH"

この定数は今回の修正で追加されたものです。サポート対象の3つのリリースラインにおける公式macOSビルド9種類で検証したところ、修正済みビルドではすべて-17が出力され、未修正の古いビルドではすべてundefinedが出力されました。ただし、パッチをバックポートしているLinuxディストリビューションではこの定数が追加されていない可能性があるため、まずはnode -vの結果を優先して信頼してください。

なお、process.versions.brotliによる確認は避けてください。24.21.0と24.22.1のどちらでも1.2.0が出力され、22.23.3と22.23.4のどちらでも1.1.0が出力されます。Node.jsはバージョン番号を変更せずに修正内容をチェリーピックしたため、このフィールドからはパッチ適用済みかどうかを判断できません。

TL;DR

項目 内容
脆弱性の概要 Node.js同梱のBrotliデコーダーにおける境界外書き込み(別名:Node2Shell、HTTP2Shell)
影響 クラッシュ、メモリ情報の漏洩、またはリモートコード実行(RCE)
深刻度 Node.js基準でHIGH、NVD基準で9.8 CRITICAL(CVSS 3.1)
悪用の有無 あり。2026年10月27日にCISA KEVへ追加
認証の要否 不要(NVDのベクターおよびAkamaiの分析による)
影響を受ける対象 外部から制御できないBrotliデータをデコードするアプリ:Express 5のリクエストボディ、fetch()のレスポンス、node:zlibの直接呼び出しなど
対策 ランタイムのアップグレード、コンテナイメージの再ビルド、プロセスの再起動
回避策 公式アドバイザリには記載なし。後述の暫定対策で攻撃対象領域を減らせるが、完全ではない
CVE-2026-111497のタイムライン:10月21日にNode.js修正版リリース、10月22日にCVE公開、10月26日に悪用トラフィックを観測、10月27日にCISA KEVへ追加、11月10日がKEV対応期限、11月11日に次回Node.jsセキュリティリリース予定

修正版がリリースされてからわずか5日後の10月26日、ELLIOはそのセンサー網で悪用トラフィックを検知したと報告しました。キャプチャされたペイロードは、x86-64環境のNode.js 24.22.0を標的としたものでした。ELLIOのテスト環境ではペイロードの最終ステージが失敗したものの、標準の24.22.0ビルドにおいてコード実行そのものが成立することは確認されています。CISAは米連邦政府機関に対して11月10日までの対応を義務付けており、ランサムウェアへの悪用状況は「不明(Unknown)」と記載しています。また、Akamaiのテレメトリデータによると、10月26日時点でネットワークの61%が影響を受けるバージョンを稼働させていました。

Node2Shellの仕組み:Brotliの脆弱性で何が起きるのか

Node2Shellは、Node.jsランタイムに組み込まれているBrotliデコーダーの境界外書き込み(Out-of-bounds write)の脆弱性です。細工された圧縮ストリームを処理すると、デコーダーが8バイトの内部バッファの終端を超えて書き込みを行い、プロセスメモリを破損させます。その結果、プロセスのクラッシュ、メモリ情報の漏洩、あるいは攻撃者による任意のコードがサーバー上で実行される恐れがあります。

根本原因は、エラー処理の誤分類にあります。無効なブロックスイッチが発生した際、「データが破損している」と判定すべきところを「入力データがさらに必要」と返してしまったため、ストリーミングデコーダーがその小さなバッファにバイトデータを追記し続けてしまいました。

このバグはGoogleのBrotliライブラリのバージョン1.0.3から1.2.0に存在するため、Node.js独自の問題ではありません。Node.js側では、アップストリームのコミット0ed4268aを24.22.1リリースおよび各ラインの修正版へチェリーピックすることで対処しました。本脆弱性はOpenAI Codex SecurityのリサーチャーであるKhai Tran氏とSylvie Mayer氏によって報告されました。

デコーダーはパッケージではなくランタイム自体に含まれているため、通常の依存関係スキャナーでは検知できません。未パッチのNode.js 24.15.0環境でExpress 5のテストプロジェクトに対してnpm installを実行しても、脆弱性は0件と報告されました。

どのような環境が影響を受けるのか(到達可能性の検証)

脆弱なランタイムを使っていることは、攻撃が成立する条件の半分にすぎません。もう半分の条件は、信頼できないBrotliデータがデコーダーへ渡る処理経路が存在することです。Node.js 24.22.1環境において、Content-Encoding: brヘッダーを付与した無害な不正ボディ(文字列not-valid-brotli)を送信するテストと、各クライアントに正常なBrotliデータを配信するテストを行い、各処理経路の挙動を検証しました。

処理経路 検証バージョン デコーダーを実行するか? 検証結果
Express 5 express.json() 5.3.0 (body-parser 2.4.0) はい(デフォルトで実行) 400、「Decompression failed」
Express 4 express.json() 4.22.3 (body-parser 1.20.9) いいえ 415、unsupported encoding
Koa @koa/bodyparser 6.1.0 はい(デフォルトで実行) 500、ログにBrotliDecoderエラー
Fastify with @fastify/compress 9.3.0 はい(プラグイン登録時) 400、FST_CP_ERR_INVALID_CONTENT
単体のFastify 5.12.8 いいえ 400、invalid JSON
素のnode:httpサーバーまたはhttp.get 24.22.1 いいえ 生のバイト列がそのまま通過
組み込みのfetch() 24.22.1 はい(常に実行) レスポンスをデコード
axios、got、node-fetch 1.21.0, 16.2.0, 3.3.2 はい(デフォルトで実行) レスポンスをデコード
zlib.brotliDecompress*、createBrotliDecompress すべて はい デコーダーAPIそのもの
node:zlib内のBrotliデコーダーに至る経路の図:インバウンド側ではExpress 5のパーサー、Koaのbodyparser、@fastify/compress付きFastify、アウトバウンド側ではfetch、axios、gotが到達する一方、Express 4、単体のFastify、素のnode:httpは到達しない

特に注目すべき結果が2点あります。まず、fetch()はリクエスト時にAccept-Encoding: identityを指定していてもBrotliをデコードしました。リクエスト側の要求ではなく、レスポンスヘッダーに従って動作するためです。アプリケーションが外部リクエストを送信する先のサーバーはいずれもこのデコーダーに到達し得るため、Webhookテスター、リンクプレビュー機能、URLインポーターなどの機能は危険にさらされます。また、単に400エラーが返ってきたからといって安全とは限りません。Express 5と単体のFastifyはどちらも400を返しますが、実際にデコーダーを実行したのはExpress 5だけでした。エラーメッセージの内容まで確認することが重要です。

影響を受ける経路が存在するかどうかは、以下の3つのコマンドで確認できます。

# Direct decoder use
grep -rnE "brotliDecompress|createBrotliDecompress" src/

# Parsers that decode request bodies
npm ls express body-parser @koa/bodyparser @fastify/compress

# Base images and pinned versions
grep -rnE "^FROM .*node" --include='Dockerfile*' .

コードにfetch()の呼び出しが1行追加されるだけでも状況は一変します。「現時点では到達不可」であっても、パッチの適用は必須です。

CVE-2026-111497のパッチ適用方法

修正の最低バージョン(フロア)ではなく、利用しているラインの最新ビルドへアップデートしてください。11月5日時点で、以下の配布元すべてで修正済みビルドが提供されています。

インストール方法 対応手順
nvm nvm install 24 && nvm alias default 24
Homebrew brew upgrade node(またはnode@24、node@22)
Docker FROM node:24.22.2-slimを指定し、docker build --pullを実行
Linuxディストリビューションのパッケージ ディストリビューションのアドバイザリに従ってください。古いバージョン番号のまま修正をバックポートしている場合があります
CI .nvmrc、engines、node-versionを更新し、再ビルドを実行
サーバーレス デプロイ済み関数からprocess.versionをログ出力して確認してください。プラットフォーム側で自動更新されていると思い込んではいけません

続いて、見落とされがちな2つの盲点に対処します。

最後に、本記事の冒頭で紹介した確認コマンドをデプロイ先コンテナ、CIランナー、開発環境で実行して確認を完了してください。各ラインの最新セキュリティビルドを確認するコマンドは以下のとおりです。

curl -s https://nodejs.org/dist/index.json | jq -r '[.[] | select(.security == true and (.version | test("^v(22|24|26)\\.")))] | group_by(.version | split(".")[0]) | .[] | max_by(.date) | "\(.version)  \(.date)"'

まだNode.js 20や25をお使いですか?その場合、修正ビルドは提供されません。Node.js 20のサポート終了(EOL)計画を確認し、速やかに移行してください。

今すぐパッチを適用できない場合の緩和策

以下の対策は時間を稼ぐためのものです。ランタイムのアップグレードに代わるものではありません。

  1. エッジでbrを拒否する。 プロキシやロードバランサーでContent-Encoding: brをブロックします。大文字小文字を区別せず、gzip, brのようなリスト形式の値にも一致するように設定してください。
  2. アプリケーション側で拒否する。 ボディパーサーの直前に以下のミドルウェアを配置します。Express 5でのテストでは415ステータスが返されました。
app.use((req, res, next) => {
  const encoding = req.headers['content-encoding'] || '';
  if (/\bbr\b/i.test(encoding)) return res.status(415).end();
  next();
});
  1. 展開(Inflation)を無効化する。 express.json({ inflate: false })を設定すると、同様のリクエストに対して415が返されます。ただし、gzip形式のリクエストボディも拒否されるため、クライアントへの影響を事前に確認してください。
  2. 外部からのレスポンスを制御する。 axiosではdecompress: falseを指定でき、検証環境でもバイト列がデコードされずに保持されました。一方、fetch()には標準的な無効化スイッチがありません。許可リストや外向き(egress)ルールを設定し、接続先ホストを制限してください。
  3. 影響範囲(ブラスト半径)を抑える。 Node.jsサービスをセグメント化してください。また、クラッシュ時にメモリ内のデータが露出する可能性があるとELLIOが指摘しているため、コアダンプの閲覧権限を制限してください。

ELLIOがいち早く検知した挙動、すなわち「どのホストがデコードを行うかを探索するための、Brotliエンコードされたリクエストボディのバースト送信」を警戒してください。JSON APIに対する想定外のContent-Encoding: brトラフィックや、ワーカプロセスの急激なクラッシュの増加は、調査すべき重要な兆候です。

アップグレード後もAPIが正常に動作するか検証する:AIエージェントを活用したテスト

ランタイムのメジャー/マイナーアップデートにより、TLS、DNS、HTTPの挙動が変わる可能性があります。10月のリリースではこれら3つすべてに変更が加えられました。差分を手作業で検証するのは避けましょう。コーディングエージェントにApidog CLIを実行させ、アップグレード前後の変化をレポートさせることができます。

npm install -g apidog-cli@latest
apidog login --with-token <YOUR_TOKEN>
npx -y skills add https://apidog.com   # pick your agent when prompted

エージェントに以下のプロンプトを与えます。

Run Apidog test suite <id> in project <id> against staging and save the
results to reports/before. After I upgrade Node.js, add a test case for
POST /orders that sends the plain text "not-valid-brotli" with
Content-Encoding: br, asserts a 4xx status, then checks GET /health
returns 200. Rerun the suite to reports/after and list every request
whose result changed.

エージェントは以下のコマンドを実行します。

apidog run --test-suite <id> --project <id> -e <envId> -r cli,junit --out-dir reports/before
apidog cli-schema get test-case-create
apidog cli-schema validate test-case-create --file case.json
apidog test-case create --project <id> --file case.json
apidog run --test-case <caseId> --project <id> -e <envId> -r cli,json
apidog run --test-suite <id> --project <id> -e <envId> -r cli,junit --out-dir reports/after

追加したテストケースは脆弱性を突くエクスプロイトではなく、ヘルスチェックのためのものです。ボディは平文テキストであり、検証環境では脆弱なビルドでも修正済みビルドでも同じパディングエラーで失敗しました。ただし、これは見落としがちな問題点を検出してくれます。Koaのテストではデコードエラーが未処理となり500エラーが返されましたが、公開APIであれば4xxを返すべきです。なお、このテストはステージング環境でのみ実行してください。

利用可能なすべてのフラグについてはrunコマンドリファレンスに、パイプラインに同様のJUnitテストを組み込む方法についてはCI/CDガイドに記載されています。ApidogのFreeプランは最大4ユーザーまで利用可能です。

なぜ次に来る11月11日が重要なのか

Node.jsプロジェクトは、2026年11月11日またはその直後に、26.x、24.x、22.xを対象とした新たなセキュリティリリースを予告しています。最高深刻度は再び「HIGH」とされています。現時点でCVE番号は公開されていません。事前の準備方法については、11月のリリースガイドで解説しています。

11月11日のリリースまで待たず、今すぐBrotliのパッチを適用してください。この脆弱性はすでに詳細が公開され、実際の攻撃トラフィックも発生しています。また、今週アップグレードを実施しておくことは、次回のリリースに対するリハーサルにもなります。同じ棚卸し手順、同じイメージ再ビルド、同じテストスイートを活用できるからです。PHP2ShellやReact2Shellの際にも同様の展開が見られました。

よくある質問(FAQ)

CVE-2026-111497は実際に悪用されていますか? はい。CISAは2026年10月27日にGoogle Brotliの項目として悪用確認済み脆弱性カタログ(KEV)に追加しており、ELLIOも10月26日の時点で悪用トラフィックを検知しています。

深刻度は「High」と「Critical」のどちらですか? 評価機関によって異なり、どちらも正式な評価です。Node.jsプロジェクトは「HIGH」と評価しています。一方、NVDのCVSS 3.1スコアは「9.8 CRITICAL」、GoogleによるCVSS 4.0スコアは「9.2」となっています。実際に悪用が確認されているという事実を前提に対応を計画してください。

Express 4を使用しています。安全でしょうか? リクエストボディがデコーダーに到達することはありませんが、fetch()、axios、およびnode:zlibの直接呼び出しは依然として影響を受けます。また、今回のリリースでは他にも9件のCVEが修正されているため、いずれにせよアップグレードすることを推奨します。

Node.js 20は影響を受けますか? サポート終了(EOL)を迎えたリリースラインはプロジェクトによる影響評価が行われず、修正パッチも提供されません。20.xおよび25.xは「未修正かつ未評価」として扱い、移行を進めてください。

Node.js以外のソフトウェアにも影響しますか? はい。影響範囲はNode.jsにとどまりません。GitHubのアドバイザリではPyPIのbrotliパッケージおよびbrotlicffiパッケージが対象として挙げられており、各ベンダーからはBun 1.4.4や.NETでの修正が報告されています。Node.jsをアップグレードしても更新されるのはNode.js同梱のデコーダーのみであるため、各デコーダーを個別にアップデートしてください。

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる