0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Brotliデコーダ脆弱性(CVE-2026-111497)の影響確認:部品台帳・実体パス・バックポートで判定する

0
Posted at

ヘッダ画像

はじめに

あきらパパです。Google Brotliのデコーダに境界外書込の脆弱性が公表されました。HTTP2Shell(CVE-2026-111497)の名前で紹介されている件です。識別子と対象範囲は、作業時点の公式告知で照合してください。

本記事は、手元の開発環境で「どこにBrotliデコーダがあり、どれが動き、外部入力が届くか」を整理したい開発者向けです。Node.js、Python、curlを中心に扱います。

  • 根拠は2026-10-25 14:51 JSTに確認した公式資料です。
  • コマンドは読み取りのみです。更新・削除・再起動のコマンドは載せません。
  • 攻撃データによる再現や、侵害有無の判定は扱いません。
  • 例はmacOS(zsh)基準です。OS差がある箇所は明記します。

概要

図1:圧縮データ→解凍処理→アプリ。問題は信頼できない入力が修正前の解凍処理に届く経路

図はすべて概念図です。実測画面ではありません。

Node.jsの告知によると、問題はBrotliデコーダの境界外書込です。細工されたBrotliデータをnode:zlibで解凍する経路が条件で、クラッシュ、メモリ漏えい、RCEの可能性が挙げられています。Node.jsの評価はHighです。https://nodejs.org/en/blog/vulnerability/october-2026-security-releases

見るべきは形式やライブラリの存在ではなく、攻撃者が制御できる入力が、修正前のデコーダに届く経路です。

修正の根拠になる公式情報

対象 修正版・根拠
Node.js 22系 22.23.4(当該修正コミットをcherry-pick)
Google Brotli(上流) 1.2.1(2026-10-21公開)
Python Brotli(PyPI) 1.2.1
brotlicffi(PyPI) 1.2.1.0
Bun 公式アドバイザリの修正情報に従う
Envoy 公式アドバイザリ(Brotli decompressorが対象)
Istio EnvoyFilter等でBrotli解凍を有効化した利用者に更新案内

出典:

注意点です。

  • Node.js 22系以外の系列は、本記事では修正版を載せていません。公式告知から辿ってください。
  • PyPIのパッケージ版と、上流libbrotliの系列別の修正版は別の番号体系です。
  • Istioのページは複数の脆弱性を扱います。ページ全体の深刻度を、Brotli単体のスコアとして読まないでください。
  • Patch the Planetのまとめは参考になりますが、検索キャッシュに古い内容が残る場合があります。版番号は個別の公式資料を優先します。https://patchtheplanet.org/brotli

判定は5つに分ける

図3:存在・選択・稼働・入力到達・修正根拠の5確認

確認 問い 主な手がかり
存在 影響する部品がディスク上にあるか node_modules、wheel、アプリ同梱
選択 実行時にその部品が選ばれるか PATH、バージョンマネージャ、venv
稼働 いま動くプロセスが使っているか PID、実体パス、起動時刻
入力到達 外部入力がデコーダに届くか 受信・取得・ファイル展開
修正根拠 修正を何で確認できるか 公式リリース記載、バックポート

「古い部品を発見」は「RCE成立」ではありません。逆に、実証できないことは安全の証明にもなりません。

部品台帳を作る

図2:アプリ内部の複数部品と別環境。OSや既定Node一つの更新では全体は置換されない

OSや既定のNode.jsを1つ更新しても、別の場所のコピーは置き換わりません。層ごとに台帳を作ります。

層 例
システム OS付属のcurl、Homebrew等のパッケージ、共有libbrotli
言語ランタイム nvm/fnm/Volta/mise/asdf等の複数Node.js、Bun、Python(venv、uv、pipx、conda)
アプリ同梱 Electron等のデスクトップアプリ、IDE、AIエージェントやMCPの付属ランタイム
ネイティブ同梱 他パッケージのwheelやネイティブ拡張に含まれる別コピー
再生成元 ロックファイル、Dockerfile、CI、コンテナイメージ、キャッシュ

よくある落とし穴です。

  • PATH先頭のnodeだけを見て、CLIごとに固定されたNode.jsを見落とす。
  • pip showしたPythonと、アプリが使うPythonが別。
  • Python Brotliを更新しても、curl-cffiやPillow等のネイティブ部品に同梱された別コピーは変わらない。なお、同梱があっても全読込経路が危険とは限らない。
  • ElectronアプリのNode表示番号を、通常のNode.js配布物と機械的に比較する。

読み取り専用で確認するコマンド

以下が返すのは、そのシェルから呼ばれた1つの環境の情報だけです。GUIアプリ、常駐サービス、コンテナ、別のvenvは別途確認が必要です。結果がどうであれ、端末全体の安全は証明できません。

Node.js

node -p "JSON.stringify({version: process.version, brotli: process.versions.brotli, execPath: process.execPath}, null, 2)"
  • version:本体の版です。Node.js公式配布の22系では22.23.4が修正版の例です。ほかの配布元では、その配布元の修正情報も照合します。
  • brotli:同梱Brotliの版表示です。バックポートでは修正後も表示が変わらない場合があるため、単独では判定しません。
  • execPath:実際に動いたバイナリのパスです。shimではなく実体が出ます。

同名のnodeが複数ないかも見ます。プロジェクトのディレクトリでも確認します。.nvmrcや.tool-versions等の指定が実際に反映されるかは、管理ツールやシェルの設定次第です。ファイルがあるだけで自動的に切り替わるとは限りません。

# macOS / Linux(zsh・bash)
which -a node
# Windows PowerShell
Get-Command node -All

Python

# macOS / Linux。Windowsでは python3 を py に置き換え
python3 -c "import sys; print(sys.executable)"
python3 -m pip show Brotli brotlicffi
  • 1行目で、どのPythonを見ているかを記録します。
  • VersionとLocationを見ます。未インストールなら警告が出ます。
  • 環境ごとに結果は別です。他パッケージに同梱されたコピーはここには出ません。

curl

curl --version

1行目にbrotli/x.y.z、Featuresにbrotliがあれば、Brotliを扱えるビルドです。表示はリンク先ライブラリの版で、配布元のバックポートは反映されないことがあります。

macOSでは、OS付属の/usr/bin/curlとHomebrewのcurl(Apple Siliconは/opt/homebrew、Intelは/usr/local配下)が併存しがちです。

# macOSのみ
which -a curl
otool -L "$(command -v curl)" | grep -i brotli

otool -Lは動的リンクのみ表示します。静的リンクなら出ないため、出ないことは不使用の証明になりません。Linuxではパッケージ管理ツールの情報で確認します。

稼働プロセスと待受

# macOS / Linux。トークン等を含むことがあるため引数は表示しない
ps -axo pid,ppid,lstart,comm
lsof -nP -iTCP -sTCP:LISTEN
  • 設定上の既定版と、いま動く実行ファイルは別物です。
  • next-server、ワーカー、MCPサーバーなど、名前がnodeでない子プロセスもあります。
  • 127.0.0.1の待受と、*や0.0.0.0の待受を分けます。
  • 待受がなくても、取得したレスポンスを解凍するクライアント側の経路はあり得ます。
  • 権限により、他ユーザーのプロセスは見えないことがあります。

入力到達を見る観点

  • 受信:Content-Encoding: brのリクエスト本文を解凍するサーバーやプロキシ。
  • 取得:外部から取得したレスポンスを解凍するクライアント(HTTPクライアント、AIエージェントのWeb取得など)。
  • ファイル:Brotli圧縮されたファイルやフォント等の展開。

Accept-Encodingからbrを外しても、相手がbrで返した場合の解凍を必ず防げるとは限りません。CDNのレスポンス圧縮を止めても、受信リクエストやクライアント側の解凍は止まりません。緩和するなら、解凍前の拒否やデコーダの無効化まで確認します。

対応の流れと判定表

図4:調査→判定→承認範囲の更新→再起動→検証→再生成確認

  1. 調査:台帳とコマンドで現状を記録する。
  2. 判定:5つの確認で分類する。
  3. 承認範囲の更新:公式アップデータやパッケージ管理の通常手順で行う。不要なメジャー更新は避ける。
  4. 再起動:親だけでなく、子やワーカーも入れ替わったかを見る。
  5. 検証:execPathと版、通常の圧縮・解凍などの正常系を確認する。
  6. 再生成確認:ロックファイル、Dockerfile、CIの版固定、キャッシュから旧版が戻らないかを見る。
分類 意味
修正済み確認 実際に使う部品に修正の根拠がある
旧部品確認・到達経路あり 優先して対応
旧部品確認・到達経路未確認 調査と更新を進める
影響の疑い 間接証拠のみ。追加情報が必要
当該経路の対象外 根拠と限定範囲を添える
未確認 理由を添える。低リスク扱いにしない

やらないこと

  • 業務端末や本番に、攻撃データを投入して確かめる。
  • 署名アプリやベンダー管理キャッシュ内のバイナリを手で差し替える。
  • 内容を確かめずに一括更新コマンドを流す。
  • 調査結果から「侵害されていない」と断定する。
  • スコアだけで順位を決める。同時期のPHP2ShellもCVSS 9.2と発表されていますが、単純な比較はしません。https://www.php2shell.com/

Codex/Claude Codeに渡すプロンプト

ここまでの手順を、ローカル環境で横断的に進めるためのプロンプトです。既定の実行モードは「ローカル対応まで」で、調査、判定、承認範囲の更新、再起動、検証、残課題の報告までを依頼します。

  • 環境を変えずに台帳だけ欲しい場合は、実行モード:ローカル対応までの行を調査のみに書き換えます。
  • 対象名とCVEは既定値が入っていますが、調査当日の一次情報で照合させる指示です。修正版番号もハードコードさせません。
  • 停止影響が不明なプロセス、OS再起動、削除、本番変更、外部送信は、まとめて確認を求める設計です。
  • 出力の一覧表では「未確認」と「残課題」を必ず読みます。共有前に、個人パスや内部URLが残っていないかも確認してください。
あなたは、端末・開発環境・依存ライブラリ・運用中プロセスを横断して調査し、根拠に基づいて修正と検証まで行うセキュリティエンジニアです。

実行モード:ローカル対応まで
対象:HTTP2Shell/CVE-2026-111497

「調査のみ」に変更された場合は環境を変更せず、情報取得と報告に留めてください。

私の環境について、脆弱性のニュースを実機の対応に変えてください。説明や更新候補の列挙で終わらず、対象の特定、影響判定、優先順位、許可された修正、再起動、動作確認、残課題の報告まで進めてください。

対象の脆弱性を別途指定していない場合は、HTTP2Shell/CVE-2026-111497として調査を開始してください。ただし、名前・CVE・影響範囲・修正版を最初から正しいと仮定せず、調査当日の一次情報で検証してください。

**1. 作業範囲と権限**

対象は、このチャットから正当にアクセスできる私の端末とローカル開発環境です。この依頼により、対象ソフトのローカル調査、バックアップ、公式更新、安全で可逆な依存更新、設定修正、影響を把握したローカル補助プロセスの再起動、通常機能の検証を許可します。

私のデータ、認証情報、作業中の変更を保全してください。停止対象と影響を確認できない重要プロセス、作業中アプリ全体の終了、OS再起動、データ削除、本番変更、公開、外部送信、認証・課金・契約操作は、必要な事前調査と具体案を用意してから、必要なものだけまとめて確認してください。許可済みの可逆な作業について同じ確認を繰り返さないでください。

秘密鍵、トークン、Cookie、パスワード、.envの値、認証を含むコマンド引数・プロセス環境を出力・外部送信しないでください。設定ファイルは必要なキーだけ調査し、バックアップに秘密情報が含まれる場合は私的領域に限定してください。

利用可能なツール、アクセス範囲、既存の運用ルールを最初に確認してください。実行権限がない場合は、実行したふりをせず、未確認の範囲と必要な最小手順を提示してください。

**2. 最初に確認する事実**

実際の日時・タイムゾーン、OS、CPUアーキテクチャ、ユーザー権限、実行環境を確認してください。MacのIntel/Apple Silicon/Rosetta、コンテナ/ホスト、遠隔環境を混同しないでください。

ベンダーのセキュリティ情報、公式リリース、修正コミット、公式パッケージ情報を優先し、次を整理してください。

- 脆弱性の実在と正しい識別子。
- 原因となる部品と処理、必要な入力・設定・権限。
- 影響する版、修正済みの版、バックポート、サポート終了系列。
- 確認された被害、公開された実証、理論上の影響の違い。
- 修正が未提供の対象と、有効な緩和策の条件。

SNSの要約、製品名の列挙、「通信するものは全部危険」といった説明をそのまま採用しないでください。CVSSだけで私の端末の危険度を決めないでください。情報に食い違いがあれば、一次情報と不確実性を明示してください。

**3. 棚卸しは実際に使われる経路から**

既存の調査・更新履歴があれば再利用し、現在の状態を確認してください。調査前の状態を記録し、同じ環境を重複して新規扱いしないでください。

次の層を、存在するものから確認してください。

- OS、ブラウザ、デスクトップアプリ、Electron/Chromium/CEF、アプリ別添のNode等。
- Node、Bun、Python、curl、共有ライブラリ、実際に使われるパッケージ管理環境。
- Volta、nodebrew、nvm、fnm、mise、asdf等の既定版・プロジェクト指定・CLI個別指定。
- Homebrew等のシステムパッケージ、uv/pipx、venv、conda、ユーザーsite-packages。
- IDE/AIエージェント/MCPの付属ランタイム、複数世代のバンドル、補助実行ファイル。
- プロジェクトの版固定、ロックファイル、CI、Dockerfile、コンテナイメージ、配布物。
- キャッシュ、旧バージョン、保管コピー、復元時に再利用される依存部品。

PATH上の先頭だけで終わらず、実体パス、シンボリックリンク、シェル・GUI・サービスごとの起動元を追ってください。同名コマンドの別コピーや、CLIごとの固定Nodeを区別してください。

停止中のDockerや未承認の遠隔環境は勝手に起動・変更せず、未確認範囲として示してください。

探索は絞り込みと段階的な追加調査で行い、無関係な巨大キャッシュを繰り返し走査しないでください。走査件数を安全性の証明として扱わないでください。

**4. 実行中プロセスを必ず確認**

設定上の既定版と、現在動いている実行ファイルは別物です。PID、親子関係、起動元、実体バイナリ、ロード済みライブラリ、待受アドレスを必要な範囲で照合してください。

プロセス名がnodeでないからといって除外しないでください。next-server、worker、MCP、ヘルパーなど、名前が変更された子プロセスも確認してください。親に待受がなくても、子が待受していることがあります。

作業ディレクトリだけで公開サーバーと断定しないでください。localhost待受、外部待受、外向き通信、トンネルを分けてください。ソケットがない瞬間の観測だけで、将来も外部入力を扱わないと断定しないでください。

再起動後は、古い親だけでなく古い子・ワーカーが残っていないことを確認してください。PIDは再利用されるため、操作直前に起動時刻・所有者・実体パス・親子関係を再照合してください。

**5. 部品の存在・利用・攻撃経路を分ける**

対象ごとに次の4点を分けて判定してください。

A. 影響する部品が存在するか。  
B. その部品が現在選択・ロードされるか。  
C. 攻撃者が制御する入力が、その問題の処理に届くか。  
D. 修正を含む実装であることを、何で確認できるか。

「古い部品を発見」を「このアプリでRCEが成立」と言い換えないでください。逆に、実証できていないことを安全の証明にもしないでください。

表示バージョンだけで判断せず、公式のバックポート、配布元独自の修正、静的/動的リンク、実際にロードされるライブラリを確認してください。文字列・シンボルの有無は補助根拠であり、単独で安全・脆弱を確定しないでください。

ElectronのNode表示番号と、通常のNode配布物を機械的に比較しないでください。エンジンが利用する依存実装と、別添の独立Nodeを分けて調べてください。製品の一部分が修正済みでも、製品全体を安全扱いしないでください。

**6. HTTP2Shellで特に見落とさない点**

Google Brotli由来の問題であることを一次情報で確認したうえで、次の経路を調べてください。

- HTTPリクエスト本文、取得したHTTPレスポンス、ファイル、フォント等の展開。
- Python Brotli/brotlicffiだけでなく、curl-cffi、Pillow/FreeType等のネイティブ部品に同梱された別コピー。
- システム共用libbrotliと、静的リンク・wheel同梱・アプリ内ライブラリの違い。
- アプリ本体、CLI、画像処理、ブラウザ操作等がそれぞれ別のランタイムを持つ可能性。

PythonのBrotliパッケージを更新しただけで、Pillowやcurl-cffiの内部も更新されたとみなさないでください。PillowにBrotliが存在しても、すべての画像読込経路を危険と断定しないでください。

Accept-Encodingからbrを外すだけでは、相手がbrを返す場合の解凍を必ず防げるとは限りません。緩和する場合は、解凍前の拒否または該当デコーダの無効化まで確認してください。CDNのレスポンス圧縮を止めただけで、クライアントや受信リクエストの解凍も止まるとみなさないでください。

過去に知られた修正版番号を恒久的な基準としてハードコードせず、調査当日の公式情報と各配布物の実装を照合してください。

**7. 判定表と優先順位**

各対象を、次のいずれかに分類してください。

- 修正済み確認:実際に使う部品に修正の根拠がある。
- 旧部品確認・到達経路あり:対応を優先する。
- 旧部品確認・到達経路未確認:調査と更新を進める。
- 影響の疑い:間接証拠のみで、確定には追加情報が必要。
- 当該経路の対象外:根拠と限定範囲を示す。
- 未確認:アクセス不可・情報不足などの理由を示す。

対応状態は別の列で「未着手/修正済み・再起動待ち/検証済み/暫定緩和/保留」に分けてください。

優先順位は、外部入力への到達可能性、稼働・選択状態、権限、データの重要性、業務への影響、修正の可逆性で決めてください。「未確認」を自動的に低リスクへ落とさないでください。

**8. 修正の実行**

変更前に、対象、変更内容、期待効果、停止範囲、復元方法を短く提示してください。既に許可されたローカルの可逆な作業は、そのまま実行してください。

公式アップデータ・パッケージ管理の通常手順を優先してください。ダウンロード先と配布元を確認し、可能なら署名、チェックサム、配布メタデータを検証してください。未検証の取得スクリプトを安易に直接実行しないでください。

互換性を保てる修正版を選び、不要なメジャー更新を避けてください。CLI本体、付属ランタイム、Python環境、ネイティブ同梱部品を別々に検証してください。更新コマンドの成功を修正完了にしないでください。

公式最新版にも旧部品が残る場合は、安全な公式配布経路、修正済み依存を使う独立環境、問題のある任意機能の停止などを検討してください。機能を減らす場合は、失われる機能を具体的に説明してください。

署名アプリやベンダー管理キャッシュ内のバイナリ手差し替え、ABI・リンク先変更は通常更新の許可に含めません。必要なら根拠、互換性、復元方法、再生成時の挙動を具体化し、別途確認してください。署名・保護機構を無効化したり、公式修正版に見せるためメタデータを書き換えたりしないでください。

暫定変更には、環境再生成・自動更新による巻戻り、外部ライブラリへの新しい依存、再検査条件を必ず記録してください。利用者の依頼なしに常駐監視や自動化を追加しないでください。

**9. 再起動と動作確認**

設定を変えただけで完了にしないでください。サービス管理方法と起動条件を確認し、保存が必要な作業を守り、対象の親子プロセスを修正版で起動してください。二重起動やポート競合を避けてください。

再起動時は必要な引数・作業場所・設定を保全し、秘密情報を出力しないでください。起動元を理解できないプロセスを機械的に停止しないでください。

実際の起動パス、実行中バイナリ、ロード済みライブラリ、正常応答を確認してください。通常データの圧縮・解凍、ローカルHTTP応答、画像・フォント処理など、変更した機能に合う小さな正常系テストを使ってください。

業務端末や本番に攻撃コードを投入して安全性を証明しようとしないでください。認証情報を伴う外部アクセスや不要な課金テストを行わないでください。必要な検証が通ったら、意味のない追加テストを続けないでください。

**10. 残存コピーと再発条件**

更新前のバイナリ、旧世代のアプリ、キャッシュ、バックアップ、CIの固定指定、過去のコンテナ・配布物を区別してください。

不使用の旧コピーを、稼働中の脆弱サービスと同じ数え方にしないでください。ただし、再選択・復元・再ビルドで旧版が復活する経路は記録してください。削除権限がないものを勝手に消さず、整理候補として示してください。

バックアップは私的な場所に置き、旧実行物を通常のPATH・自動起動から外してください。復元手順には「旧脆弱性も戻る」ことを明記してください。

自分を動かす宿主の停止は証跡と再開手順を保存して最後に行ってください。失敗時は変更を広げず復旧し、脆弱な旧版へ戻した場合は未解決として緩和策を示してください。旧版互換性テストと本番用ビルドを区別し、テスト対象を無断で削らないでください。

**11. 最終成果物**

まず結論を短く伝え、次の一覧表を出してください。

対象|所在・起動元|変更前|変更後|影響判定と根拠|実施した対応|検証結果|残課題|優先度

続いて、次を簡潔にまとめてください。

- 通常更新で対応完了したもの。
- 暫定対応・機能制限を伴うもの。
- 再起動待ち、未対応、追加権限・ベンダー修正待ちのもの。
- ローカル調査では判断できなかった本番・クラウド・他端末。
- バックアップ場所、復元方法、再発時の確認方法。
- 調査日時、一次情報へのリンク、秘密情報を除いたローカル証跡。

ファイルを作れる場合は、詳細Markdownと対応一覧CSVを保存してリンクしてください。過去の調査スナップショットを現在の事実で上書きせず、今回の実施結果を区別してください。

**12. 完了判定**

「存在する」「選択される」「実行中」「攻撃経路がある」「修正がある」を混同しないでください。

修正完了とする条件は、対象の実行経路で修正済み部品が使われ、必要な再起動が済み、通常機能の検証が通り、今回の対象に未処理の旧経路が残っていないことです。満たせない条件があれば、達成した部分と残った部分を明示してください。

私の環境全体が安全、侵害されていない、すべて対応済みといった包括的な結論を、調査範囲を超えて出さないでください。情報が不足していても調査だけで止まらず、許可された範囲の修正を進め、最後に私が判断すべき事項だけを残してください。

製品数、部品コピー数、環境数、プロセス数を別集計にし、共有版では個人パス・内部URL・秘密情報を伏せてください。まず読み取り中心の調査を開始し、指定モードで許可された対応と検証まで進めてください。

まとめ

「存在」「選択」「稼働」「入力到達」「修正根拠」を分けて記録すると、ニュースを手元の対応に落とし込めます。コマンドの結果は1環境分の事実です。確認できなかった欄は「未確認」と理由を残すことが次の調査につながります。

この記事のもとにした著者のX投稿です。https://x.com/akira_papa_IT/status/2114230636667973665

資料確認日時:2026-10-25 14:51 JST

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?