This is some text inside of a div block.
< ブログ一覧に戻る

Node2Shell(CVE-2026-111497):Node.js Brotli RCE の検出

清水 孝郎
Node2Shell(CVE-2026-111497):Node.js Brotli RCE の検出
執筆者
清水 孝郎
Subscribe to Threat Research
Node2Shell(CVE-2026-111497):Node.js Brotli RCE の検出
Published:
October 26, 2026
この記事の内容
TRT in your inbox

Get security briefings from the Threat Research Team

New campaigns, attacker techniques, and detection guidance — straight to your inbox.

Subscribe
シスディグによるファルコフィード

Falco Feedsは、オープンソースに焦点を当てた企業に、新しい脅威が発見されると継続的に更新される専門家が作成したルールにアクセスできるようにすることで、Falcoの力を拡大します。

さらに詳しく
Green background with a circular icon on the left and three bullet points listing: Automatically detect threats, Eliminate rule maintenance, Stay compliant, with three black and white cursor arrows pointing at the text.

本文の内容は、2026年10月24日に Sysdig 脅威リサーチチーム(TRT)が投稿したブログ (https://www.sysdig.com/blog/node2shell-cve-2026-111497-detecting-the-node-js-brotli-rce) を元に日本語に翻訳・再構成した内容となっております。

不正な形式の圧縮ストリーム、無視されたエラー、そしてバッファの末尾を超える書き込み。2026年10月21日、Node.js は、同梱している Brotli デコーダーの境界外書き込みを修正したバージョン、22.23.4、24.22.1、26.12.1 をリリースしました。その1日後の10月22日、Imperva は、Linux arm64 向けの公式 Node.js 24.22.0 Docker イメージ上でコードを実行できたと報告しました。現在 CVE-2026-111497 として追跡されているこの脆弱性は、CVSS v4.0 のベーススコアが 9.2(Critical)と評価されており、広く Node2Shell と呼ばれています。 

10月23日の時点で、実環境での悪用は確認されておらず、Node2Shell は CISA の Known Exploited Vulnerabilities(KEV)カタログにも追加されていません。しかし、公開された概念実証(PoC)コードはすでにテストされており、パッチの公開から PoC の登場までの間隔は約1日でした。セキュリティチームは、自社の Node.js サービスが、自分たちで管理していない Brotli データをデコードしているすべての箇所を洗い出し、まずそこからパッチを適用するよう取り組む必要があります。

Sysdig 脅威リサーチチーム(TRT)は、公開されている Node2Shell のリサーチを分析し、防御担当者が、誰が攻撃の到達範囲にいるのか、何が実証され何が主張にとどまっているのか、ランタイムの可視化で何を検知できるのか、そして組織がパッチ適用を始められるまでの間に何ができるのかを把握できるようにしました。

タイムライン

日付

イベント

2026年10月14日

Node.js がリリースを事前告知し、影響を受けるラインと、最大の深刻度が High であることを明示

2026年10月21日 10:38 UTC

Node.js が v22.23.4、v24.22.1、v26.12.1 を公開

2026年10月21日 15:47 UTC

この CVE に関する最初の公開 GitHub リポジトリが登場(修正のリリースから約5時間後)

2026年10月21日 約19:27 UTC

Brotli プロジェクトが 1.0.10、1.1.1、1.2.1 を公開(いずれも CVE-2026-111497 を記載)

2026年10月22日

Google の CVE レコードが、CVSS v4.0 でスコア 9.2 として公開される

2026年10月22日

Imperva が、Node.js 24.22.0 でのコード実行を示すリサーチを公開

影響を受ける Node.js のバージョン

このバグ自体は Node.js のコードではなく、Brotli にあります。Node.js は独自のコピーを同梱しているため、修正するにはランタイム自体を更新する必要があります。

Node.js のアドバイザリでは、この脆弱性の深刻度は High とされています。Google は CVSS v4.0 で 9.2 の Critical と評価しています。ただし、深刻度は、コードがデコーダーに到達するかどうかで決まるエクスポージャーによって変わる可能性があります。

Node.js のバージョン

サポート終了日

修正バージョン

26.x

2029年4月30日

26.12.1

24.x

2028年4月30日

24.22.1

22.x

2027年4月30日

22.23.4

25.x

2026年6月1日(終了済み)

修正なし

20.x

2026年4月30日(終了済み)

修正なし

Node.js は、サポート終了(EOL)バージョンはセキュリティリリースの影響を常に受けると明言しています。Node.js 25、20、またはそれ以前を実行している組織は、これらのホストを脆弱であるとみなす必要があります。今後パッチが提供されることはありません。 

ディストリビューションのパッケージは、別途確認が必要です。Debian のトラッカー(10月23日に確認)では、bookworm の nodejs 18.20.4、trixie の 20.19.2、forky の 24.21.0、sid の 24.22.0 が脆弱であるとされており、Debian の nodejs はシステムの Brotli ライブラリを使用していると記載されています。この場合、修正はランタイムだけでなく、ライブラリ側に適用されます。 

Debian の Brotli パッケージも、トラッカーに記載されているすべてのリリースで脆弱であり、どのリリースにも修正バージョンは示されていません。また、トラッカーでは、Debian の開発ブランチである unstable でも brotli と nodejs の両方が未修正と表示されています。10月23日の時点で、どちらのコンポーネントについても、Debian のパッチ適用済みパッケージはありません。Debian は nodejs のエントリを緊急度「unimportant」と評価しており、Node.js が割り当てた High とは異なりますが、トラッカーはその理由を示していません。

CVE レコードは、根本的なバグを Google の Brotli ライブラリ 1.0.3 から 1.2.0 にあるものとしており、修正は 1.0.10、1.1.1、1.2.1 で提供されています。この範囲の Brotli ビルドを同梱している他のソフトウェアも、追加の分析やベンダーへの問い合わせを行う価値があります。 

ただし、影響は Debian に限りません。Ubuntu、Fedora、RHEL、Alpine のパッケージも、同梱のコピーではなくシステムの Brotli ライブラリを使用している可能性があります。そのため、修正はディストリビューションの Brotli パッケージを通じて提供されることになり、Node.js のバージョン番号だけでは、特定のインスタンスにパッチが適用されているかどうかを判断できません。

Aikido によると、Bun も影響を受けます。1.4.3 以前のすべてのバージョンが脆弱で、Bun 1.4.4 に修正が含まれています。 

Node2Shell のバグ(CVE-2026-111497)の仕組み 

Brotli は圧縮フォーマットです。Node.js は、zlib モジュールのネイティブデコーダーを通じてこれをサポートしています。CVE レコードは、c/dec/decode.c のバッファオーバーフローを説明しており、2種類の弱点として、境界外書き込み(CWE-787)と、戻り値の未チェック(CWE-252)を挙げています。

2つ目の弱点が、仕組みを説明しています。細工されたストリームは、1種類のデータブロックを宣言した上で、デコーダーにブロックタイプの切り替えを要求します。正しいデコーダーは、ここでエラーを出して停止します。パッチ未適用のデコーダーはエラーを無視して処理を続け、バッファの末尾を超えて書き込みます。Semgrep は、根本的な欠陥を、デコーダーが不完全な入力と無効な入力を取り違え、不正な形式のストリームの処理を続けてしまうことだと説明しています。 

修正は小規模です。Node.js は、ストリームが1種類のブロックタイプしか宣言していない場合に、ブロックの切り替えでデコーダーを即座に失敗させる、上流の Brotli のコミット(0ed4268a)をチェリーピックしました。Node.js は、新しいエラー定数 BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH も追加しています。

到達可能な経路

Node.js が単独で Brotli をデコードすることはありません。アプリのコード、またはそのアプリが使用するライブラリが、攻撃者の制御する Brotli データを展開する場合に、そのアプリは影響を受けます。Semgrep は、いくつかの入り口を確認しました。 

経路

デコーダーに到達するか

詳細

Express 5 と express.json()

はい(デフォルトで到達)

Express 5.3.0 は body-parser ^2.3.0 に依存しています。body-parser 2.x は br のボディをデコードし、inflate オプションはデフォルトで true です。素の Node.js HTTP サーバーは、受信した Brotli のボディを単独ではデコードしません。

Express 4 と express.json()

body-parser 経由では到達しない

body-parser 1.20.x は deflate と gzip のみを処理し、それ以外のエンコーディングには 415 を返します。

サーバーサイドの fetch()

はい(攻撃者が影響を及ぼせるレスポンスの場合)

Node.js の fetch は、Content-Encoding ヘッダーに br が含まれていれば、常に Brotli デコーダーでレスポンスを展開します。Accept-Encoding: identity を送信しても防げません。Webhook のように、ユーザーが指定した URL を呼び出す機能が、典型的な標的になります。

node:zlib の直接利用

はい

createBrotliDecompress() は、攻撃者が制御するデータを受け取る場合に、攻撃にさらされます。

Koa(co-body 経由)

はい

Brotli のリクエストボディは co-body を経由して展開されます。Semgrep は、@koa/bodyparser、koa-body、Egg、Strapi も挙げています。

Fastify と @fastify/compress

はい

このプラグインを登録すると、Fastify の content-type パーサーが実行される前に、リクエストの展開処理が追加されます。

優先すべきは受信側の経路です。body-parser をグローバルにマウントしている場合、content-encoding とパーサーの条件を満たせば、ボディを受け付ける多くの公開ルートに到達する可能性があります。ただし、送信側の経路も重要です。組織のサービスが、攻撃者の管理するサーバーからデータを取得する場合、そのレスポンスによってサービスが攻撃される可能性があります。

これは、Express 4 が安全であることを意味するものではありません。この結果は body-parser にのみ当てはまります。他のミドルウェア、フレームワーク、リバースプロキシ、そして組織独自のコードが、Brotli をデコードしている可能性は残っています。 

Node2Shell の悪用:実証されたことと主張されていること

Imperva は、Linux arm64 上の公式 Node.js 24.22.0 イメージに対するコード実行を実証しており、実行には複数回の試行が必要だったと述べています。デバッガーや改変されたバイナリのない、起動直後のコンテナーでは、このテストはマーカーファイルの作成で終了し、パッチ適用済みの 24.22.1 は、同じ入力をフォーマットエラーで拒否しました。Imperva は、エクスプロイトコードを公開していません。 

公開されている PoC が何をするかについては、10月22日 20:28 UTC の時点で、GitHub の検索で11件のリポジトリが見つかりました。あるラボは、Node.js 20.19.5、22.23.3、24.22.0、26.12.0 でクラッシュを確認したと報告しており、修正版の 22.23.4、24.22.1、26.12.1 は同じ入力を拒否すると述べています。別のチームは、3回中3回でローカルコマンド実行に成功したと報告しましたが、それには、未修正のシステム Brotli ライブラリをロードするビルドと、予測可能なメモリレイアウトが必要でした。このチームは、アドレスのランダム化が有効な状態でのブラインドなリモート実行は成功しなかったと述べています。 

ただし、証拠の一部は不十分です。あるリサーチは、どの Brotli ストリームも問題の書き込みには到達できず、実際の影響はサービス拒否(DoS)であると主張しています。修正コミットの入力を Node.js 24.22.0 で独立してテストしたところ、修正前のビルドでも修正後のビルドでもエラーが発生したため、このテストだけでは書き込みが起きることを示せません。Konfirmity は、修正コミット自体が、このバグを深刻度が低く、悪用が容易ではないものと説明していると指摘しています。 

信頼性のあるリモートコード実行(RCE)が再現されたのは、これまでのところ1つの構成だけです。一方、クラッシュはリサーチャーにとって簡単に再現できています。組織は、どこでもクラッシュが起こり得る結果だと想定し、攻撃者が制御している可能性のある Brotli をサービスがデコードしている場所では、シェルの奪取も現実的なリスクだと考えるべきです。  

Node2Shell の影響

公開時点で公に開示されている情報には、ワーム、大規模な悪用キャンペーン、プラットフォームをまたいで信頼性のあるエクスプロイトがあることを示すものはありません。しかし、リサーチャーは次のことを実証しています。

  • サービス拒否(DoS): 公開 PoC の作者たちは、前述のリポジトリによると、パッチ未適用の Node.js でプロセスがクラッシュすると報告しています。攻撃者は、ユーザーからの Brotli をデコードするあらゆるサービスを停止させることができます。
  • Node.js プロセス権限でのコード実行: Imperva は、1つのイメージとアーキテクチャで、複数回の試行によりこれを実証しました。攻撃者のコードは Node.js プロセスの権限で実行され、データを盗み出す可能性があります。 
  • メモリの漏えい: Vercel によると、リサーチャーは、パッチ未適用の 22.x、24.x、26.x で、Node.js プロセス内のメモリの漏えいとコマンド実行を実証しました。コード実行に失敗した場合でも、漏えいしたメモリから認証情報などのデータが露出する可能性があります。 

Node2Shell の検知方法

マネージドポリシーを利用している Sysdig Secure のお客様は、Node2Shell を特定して対応するための検知機能をすでに利用できます。Threat Intelligence のエントリでエクスポージャーのある場所を確認でき、ランタイムルールが、エクスプロイトと、その後の攻撃者の活動を捕捉します。

Threat Intelligence

Sysdig Threat Intelligence フィードに、Node2Shell のエントリが公開されました。ここには、修正済みリリースの 26.12.1、24.22.1、22.23.4 よりも古い Node.js バージョン、またはサポート終了のラインを実行しているホストとワークロードが一覧表示されます。ホストまたはワークロードの件数を選択すると、影響を受けるアセットを絞り込んだ検索が開きます。

ランタイム検知
悪用がきれいに成功することはまれです。失敗した試行は Node.js プロセスをクラッシュさせ、Imperva 自身のデモでも複数回の試行が必要でした。Sysdig Runtime Behavioral Analytics ポリシーに追加された新しいマネージドルール Node.js Process Crash Followed by In-Place Program Execution は、同じワークロード内で、Node.js のクラッシュと、それに続く不審なプログラム実行を関連付けます。これが Node2Shell の攻撃チェーンのパターンです。

エクスプロイトが成功した場合、攻撃者は Node.js サービスのユーザーとしてコマンドを実行できます。その後の一般的な行動には、インタラクティブシェルの起動、マルウェアのダウンロード、暗号資産マイニング、コンテナーからのシークレットやクラウドトークンの窃取があります。Sysdig Secure がデフォルトで有効にしているマネージドポリシーは、この種の活動にすでにアラートを出します。エクスプロイト自体が見逃された場合でも、お客様は保護されています。

Node2Shell の緩和方法

パッチ

  • 更新する: Node.js を 22.23.4、24.22.1、または 26.12.1 に更新してください。Imperva は、デコーダーを修正できるのは Node.js の更新だけだと述べています。 
  • アップグレードする: Bun が動作しているすべての場所で、1.4.4 以降にアップグレードしてください。
  • 再ビルドする: パッチ適用済みのベースイメージからコンテナーイメージを再ビルドし、実行中のコンテナーで node --version を使って確認してください。node:24 のようなフローティングタグは、キャッシュ済みのイメージから再ビルドすると古いバージョンのままになるため、先に docker pull を実行してください。Dockerfile のピン留めを 24.22.1 以降に移行してください。
  • 確認する: 思い込みを避け、パッケージマネージャーを確認してください。Homebrew は、リリースの約10時間後も、node 26.12.0、node@24 24.22.0、node@22 22.23.3 を配布していました。
  • 置き換える: Node.js 20 以前を、22.x または 24.x に置き換えてください。これらに修正は提供されません。

パッチ適用までに到達可能性を減らす

  • 無効化する: 可能な場合は、リクエストの展開を無効にしてください。body-parser では、express.json({ inflate: false }) とすると、圧縮されたボディは 415 で拒否されます。事前にクライアントをテストしてください。これは gzip も拒否します。
  • 拒否する: クライアントが送信しない環境では、プロキシまたはロードバランサーで、リクエストボディの Content-Encoding: br を拒否してください。Brandefense はこれを独自の提案として示しており、ベンダーのガイダンスではありません。頼りにする前にテストしてください。サービスが取得するレスポンスは対象外です。 
  • 監査する: 自分たちが管理していないサーバーへの fetch 呼び出しと、createBrotliDecompress() の直接利用を監査してください。
  • 重ねる: WAF がある場合は、防御を重ねてください。Imperva は、WAF ルールを追加し、影響を受けるパスでは信頼できない Brotli トラフィックを制限することを推奨しています。これはあくまで追加の防御層であり、修正の代わりにはなりません。 

影響範囲を抑え込む

  • 実行する: Node.js サービスは非特権ユーザーで実行し、可能な限り、シークレットをプロセスの環境変数に置かないでください。コード実行は、Node.js プロセスの権限で行われます。 
  • 監視する: Web に公開されている Node.js プロセスについて、シェルの起動や、想定外の外向き接続を監視してください。

環境全体で

  • 棚卸しする: コンテナー、CI ランナー、サーバーレス関数、ビルドサーバー、独自の Node.js を同梱するツールなど、すべての Node.js ランタイムを棚卸ししてください。

まとめ

Node2Shell は、すべての Node.js サービスのバグではなく、攻撃者が影響を及ぼせる Brotli をデコードするサービスのバグです。Express 5 のデフォルトの JSON パースは、そうしたインスタンスを数多く、そのグループに入れてしまいます。これまでに実証された影響は、大規模なクラッシュと、限られた構成でのコード実行であるため、パッチの適用順序は到達可能性に従うべきです。

しかし、本当の警告はタイムラインにあります。Node2Shell の場合、この CVE を追跡する公開リポジトリは修正のリリースから5時間後に登場し、動作する PoC は1日以内に公開されました。この欠陥は、Node.js をはじめ複数のソフトウェアが同梱するネイティブライブラリにあるため、それぞれが独自に修正を提供しなければなりません。そのため、セキュリティチームは、ランタイムの下にあるネイティブライブラリでこうした欠陥がさらに見つかり、その時間的猶予がますます短くなることも想定しておくべきです。 

セキュリティチームにとって、今週の作業は、まずインベントリ、次に到達可能性の順でのパッチ適用、そしてパッチが未適用のまま残るものに対する最小権限の徹底です。ランタイムセンサーはオーバーフロー自体を捉えることはできませんが、エクスプロイトが成功した後に何が起きるかは捕捉します。だからこそ、ポストエクスプロイトの挙動は、注目に値する最後の砦なのです。

‍

About the author

featured resources

セキュリティの専門家と一緒に、クラウド防御の最適な方法を探索しよう