本文へ移動
AI-nativeエンジニアリング

NGINX 1.30.6と1.31.7:10月のアドバイザリー後にアップデートすべき理由

10月14日のNGINXリリースは設定依存の脆弱性5件を修正:実際のバージョン確認、見直す設定、固定方法。

公開日 更新日 8 分で読める
NGINXsecurityDevOpsNode.jspatching

この記事は教育目的であり、正式なスマートコントラクト監査、法的助言、金融助言、またはプロトコル固有のセキュリティレビューに代わるものではありません。

2026年10月14日、nginx.orgはstableブランチのnginx 1.30.6と、mainlineブランチのnginx 1.31.7を公開しました。どちらも重大度「中」の脆弱性5件を修正しています。そのうち4件は何年も前に公開されたバージョンに影響し、いずれも特定の設定、たとえばHTTP/3やaliasとrewriteの組み合わせでのみ発生します。

NGINX Open Sourceで本番トラフィックを処理しているなら、1.30.6、または1.31.7以降、あるいはディストリビューションのパッチ適用済みパッケージにアップデートしてください。設定の確認は作業の順番を決めるためのもので、影響を受けるバージョンにとどまる理由にはなりません。設定は時間とともに変わり、パッチ適用済みのバージョンはその分析に依存しなくなります。

白い大理石のモジュールに収まった4つのコバルトブルーのガラスカートリッジ。手が新しい1つを差し込んでおり、手前には琥珀色の帯が付いた古いすりガラスのカートリッジが置かれ、上には5つのライトが灯っている。3つはコバルトブルー、2つは琥珀色である。
コンセプトイラスト。

この記事では、これらのバージョンが何を修正するのか、サーバー、パッケージ、コンテナイメージで実際に動いているNGINXをどう確認するか、どのディレクティブを探すべきか、そして新しいバージョンが元に戻らないようにどう固定するかを説明します。最後に、Node.jsの実例で、同じパターンを別のコンポーネントに当てはめた例を紹介します。

1.30.6と1.31.7で修正される内容

nginx.orgの変更履歴によると、10月14日の5件の修正は次のとおりです。

  • CVE-2026-15176:rewriteで変更されたURIをaliasディレクティブが処理する際に、ワーカープロセスでバッファオーバーフローが起きる。影響は0.1.29から1.31.6まで。
  • CVE-2026-93479:変数を含む式の評価時のバッファオーバーフロー。httpモジュールとstreamモジュールでのrootの計算とログ出力に関係する。影響は1.30.0から1.30.5まで、および1.31.2から1.31.6まで。
  • CVE-2026-95101:HTTP/3使用時に、未知のフレームの一部がリクエストボディとして扱われることがあり、client_max_body_sizeの回避や、バックエンドへ送られるリクエストへのデータ注入につながる。影響は1.25.0から1.31.6まで。
  • CVE-2026-97629:TLSセッションチケットキーのローテーション時に、キーの1つが初期化されないままになり、セッションの偽造につながるおそれがあった。影響は1.23.2から1.31.6まで。
  • CVE-2026-97205:非同期ファイルI/O(aio)使用時に、include virtualコマンドを含むSSIページがuse-after-freeを引き起こすことがある。影響は0.8.11から1.31.6まで。

nginx.orgはこれらを重大度「中」と評価しています。NGINXのCVEを割り当てるF5は、NVDでCVSS 3.1のスコアを5.3から8.1の範囲で公開しています。10月23日時点で、NVDは5件のいずれについても独自の分析を終えていません。

1.30.4より前のバージョンを使っている場合、今回のアップデートにはそれ以前の修正も含まれます。最も重要なのはCVE-2026-42533で、nginx.orgは「major」と評価し、7月15日に1.30.4で修正しました。正規表現を使うmapと、そのmapのキャプチャを組み合わせたときにメモリのオーバーフローが起きるものです。10月21日に公開されたmainlineの1.31.8には、セキュリティ修正は含まれていません。

設定が該当しなくてもアップデートすべき理由

これらの脆弱性は、それぞれ特定の組み合わせを必要とします。aliasとrewrite、HTTP/3、TLSチケットのローテーション、aioとSSIです。設定を確認して、これらのディレクティブが見つからなければ、バージョンをそのままにしたくなります。そうしない理由は3つあります。

1つ目は、設定は変わるということです。新しいinclude、別のチームのテンプレート、あるサーバーでのHTTP/3の有効化によって、誰もアドバイザリーを見直さないまま、再び影響を受ける状態になることがあります。パッチ適用済みのバージョンは、その分析が正しいままであることに依存しません。

2つ目はコストです。1.30.6は1.30.5と同じブランチに属し、変更履歴に載っているのは修正と、一部のログメッセージのレベル変更だけで、新機能はありません。stableブランチでは、例外を維持してその理由を説明し続けるより、アップデートするほうが通常は手間がかかりません。

3つ目は、古いブランチにはnginx.orgからこれらのパッチが提供されないことです。ダウンロードページでは1.28や1.26などがlegacyバージョンとして掲載されており、アドバイザリーで修正済みとされているのは1.30.6と1.31.7以降だけです。これらのブランチを使っているなら、移行先は1.30.6か、ディストリビューションのパッチ適用済みパッケージです。

ステップ1:実際に動いているNGINXを確認する

重要なのはトラフィックを処理しているバイナリのバージョンで、READMEやイメージタグに書かれたバージョンと一致するとは限りません。

bash
# バイナリのバージョン
nginx -v

# 組み込まれたモジュール:HTTP/3 は --with-http_v3_module として表示される
nginx -V 2>&1 | tr ' ' '\n' | grep -E 'http_v3|file-aio|threads'

# Debian と Ubuntu:パッチが適用済みかどうかはパッケージのバージョンでわかる
apt-cache policy nginx

# コンテナ:イメージ内の実際のバージョン
docker run --rm nginx:1.30.6-alpine nginx -v

ディストリビューションのパッケージでは、nginx -vの数字が誤解を招くことがあります。ディストリビューションは、メインのバージョン番号を変えずに自分たちのバージョンにパッチを当てることがよくあります。たとえばDebian 13では、アドバイザリーDSA-6575-1によると、10月の5件のCVEを修正するパッケージは1.26.3-3+deb13u10ですが、nginx -vは1.26.3のままです。比較すべきなのは、パッケージの完全なバージョンと、ディストリビューションのアドバイザリーに書かれたバージョンです。

Kubernetesでは、イングレスコントローラーやサードパーティのイメージが独自にビルドしたNGINXを含んでいることがあります。たとえばnginx.orgのページでは、自社のNGINX Ingress Controllerとコミュニティプロジェクトのingress-nginxを区別しています。こうした場合、パッチ適用済みのバージョンを公開するのは、そのコントローラーやイメージのメンテナーです。

ステップ2:設定で使われているディレクティブを確認する

nginx -Tは設定を検証し、すべてのincludeを展開したうえで全体を出力します。grepで絞り込むと、今年のアドバイザリーに関係するディレクティブの最初のリストが得られます。

bash
# 設定全体(include を展開済み)を、アドバイザリーに関係するディレクティブで絞り込む。
# 行番号は nginx -T の出力の行番号で、各ファイルの行番号ではない。
sudo nginx -T 2>/dev/null | grep -nE '^\s*(alias|rewrite|map|aio|ssi|http3|ssl_session_cache|ssl_session_ticket_key)\b|\$request_filename|\bquic\b'

F5がNVDで各CVEについて公開している説明に基づく、結果の読み方は次のとおりです。

  • aliasとrewriteに加えて、$request_filename変数を参照するsetまたはreturnディレクティブを使うlocation、またはアクセスログの書式(log_format)での$request_filenameは、CVE-2026-15176に該当します。
  • 正規表現を使うmapで、そのキャプチャ変数がrootまたはアクセスログの書式の中でmapの出力変数より前に現れる場合は、CVE-2026-93479に該当します。変数を含む任意の式でそのように現れる場合は、CVE-2026-42533に該当します。
  • quic付きのlisten、またはhttp3 onは、CVE-2026-95101に該当します。
  • ssl_session_ticket_keyなしのssl_session_cache sharedは、CVE-2026-97629に該当します。
  • aioとssiの併用は、CVE-2026-97205に該当します。

一致したからといって脆弱性を悪用できるとは限らず、一致しなかったからといって完全に否定できるわけでもありません。grepにはサードパーティのモジュールも、起動時に生成される設定も見えないからです。これは作業の順番を決めるためのものです。一致したサーバーを先に対応し、残りも同じようにアップデートします。

ステップ3:アップデートしてバージョンを固定する

パッケージを使っているサーバーでは、各システムの通常の手順でアップデートします。新しいパッケージをインストールし、nginx -tで検証し、新しいバイナリがトラフィックを処理するようにサービスを再起動します。nginxのドキュメントによると、リロードは設定を読み直すだけです。バイナリを切り替えるには、再起動するか、USR2シグナルによるオンザフライのアップグレードが必要です。

コンテナでは、イメージをタグとダイジェストの両方で固定するのがよいでしょう。タグはどのバージョンを意図したかを示し、ダイジェストは、誰かが同じタグを再公開しても、確認したイメージそのものを固定します。

dockerfile
# 読みやすいタグと不変のダイジェスト。
# ダイジェストの取得方法:crane digest nginx:1.30.6-alpine
FROM nginx:1.30.6-alpine@sha256:47928bf67eb62a1863cb08d9ecb52d3e704304ba614eaee17884204677702951

この例のダイジェストは、2026年10月23日にこのタグが返したものです。タグは、たとえばイメージの再ビルド時に、別の内容で再公開されることがあります。ダイジェストは固定するその時点で取得してください。

バージョンが元に戻らないように、修正版より古いNGINXイメージを使うDockerfileやマニフェストがあれば失敗するチェックをCIに入れられます。

bash
#!/usr/bin/env bash
# 1.30.6(stable)または 1.31.7(mainline)より古い NGINX イメージを使う Dockerfile や YAML マニフェストがあれば失敗する。
set -euo pipefail
refs=$(grep -rhoE --include='Dockerfile*' --include='*.yaml' --include='*.yml' \
  '(nginx|nginxinc/nginx-unprivileged):[0-9]+\.[0-9]+(\.[0-9]+)?' . | sort -u || true)
bad=0
for ref in $refs; do
  ver=${ref##*:}
  IFS=. read -r major minor patch <<< "$ver"
  patch=${patch:-0}
  if (( major < 1 || ( major == 1 && ( minor < 30 || (minor == 30 && patch < 6) || (minor == 31 && patch < 7) ) ) )); then
    echo "Needs update: $ref"; bad=1
  fi
done
exit $bad

このスクリプトが認識するのは、バージョン番号を含むタグだけです。stable-alpineやlatestのようなフローティングタグには比較できる数字がありません。これも、バージョンとダイジェストの両方で固定すべき理由の1つです。

実例:Node.jsでの同じパターン

10月21日、Node.jsはバージョン24.22.1、22.23.4、26.12.1を公開しました。複数の脆弱性を修正しており、最も深刻なものはプロジェクト自身の評価で重大度「高」です。あわせてルート証明書をNSS 3.131.1に更新しており、Node.jsのアドバイザリーはこの更新をeMudhraの中間CAの侵害と結びつけています。

eMudhraの侵害については、macOSの開発ツールで何を更新すべきかを扱った記事があります。

本番環境で動いている、複数のコンテナイメージを持つNode.jsプロジェクトでは、この更新がすでに開発ブランチに入っています。そのうち3つのやり方は、NGINXにもそのまま使えます。

  • すべてのイメージをnode:24.22.1-alpineに移行し、タグとダイジェストで固定した。
  • 独自のNode 22を含んでいた補助イメージと、Node 20を使っていた古いベースイメージも、同じバージョンに移行した。
  • package.jsonでengines.nodeを>=24.22.1と宣言し、CIには古いバージョンのイメージを拒否するチェックがある。
bash
# アプリを起動せずに、イメージ内の Node のバージョンを確認
docker run --rm node:24.22.1-alpine node -v

# イメージを固定するためのダイジェスト
crane digest node:24.22.1-alpine

# 修正済みの 24.x 系のみ(>=24.22.1 <25)。--engine-strict を付けると、この範囲外の Node では npm install が失敗する
npm pkg set engines.node='^24.22.1'
npm install --engine-strict

この教訓はそのまま当てはまります。セキュリティアップデートは1行を変えたときに終わるのではありません。バージョンがイメージで固定され、プロジェクトで宣言され、CIで確認されて、後の変更が誰にも気づかれずにそれを元に戻せなくなったときに終わります。

今回のアップデートが対象としないもの

NGINXを自分で管理していないなら、パッチも自分の担当ではありません。CDNやマネージドプラットフォームがアプリケーションの前に置く独自のプロキシは、そのプロバイダーが更新します。やるべきことは、自分が実際に管理しているコンポーネントを把握することです。同じファミリーの他の製品も対象外です。たとえばnjsは、同じ10月14日に、別の修正を含む独自のバージョン1.0.2を公開しました。

アップデート、固定、確認

10月14日のアドバイザリーが求めているのは、慌てて対応することではなく、作業を最後まで終えることです。どのNGINXがトラフィックを処理しているかを把握し、1.30.6または1.31.7にアップデートし、イメージをダイジェストで固定し、元に戻るのを防ぐチェックをCIに残してください。

このプロセスを自社のインフラにどう適用するか相談したい場合は、お問い合わせページからご連絡ください。メッセージではこの記事に触れていただき、認証情報や機密性の高い設定の詳細は含めないでください。

参考資料

出典は2026年10月23日に参照しました。Linuxで実行し、出力を保存したもの:nginx.orgの1.30.6パッケージとDebian 13の1.26.3パッケージでのnginx -vとnginx -V、テスト用の設定でのnginx -Tとディレクティブの絞り込み、テスト用マニフェストでのCIスクリプト、記事中のイメージに対するcrane digest、craneで展開したnginx:1.30.6-alpineとnode:24.22.1-alpineのイメージ内のNGINXとNodeのバージョン、npm pkg setとnpm install --engine-strict。実行していないもの:docker run(craneによるイメージの展開で代替)、およびサーバーでのアップデートとサービスの再起動。

この内容をローンチやワークフローに適用したいですか?

技術レビューを依頼し、最も安全な第一歩を整理しましょう。

関連記事