Node.js が一気に塞いだ「TLSホスト名検証バイパス」4種 - 2026年6月の緊急アップデートを読み解く

Node.js が一気に塞いだ「TLSホスト名検証バイパス」4種 - 2026年6月の緊急アップデートを読み解く

作成日:
読了:12
更新日:

2026年6月18日、Node.jsプロジェクトが全アクティブリリースライン(22.x / 24.x / 26.x)で一斉のセキュリティアップデートを公開しました。修正されたCVEは合計12件、うちHIGHが2件です。パッチ済みバージョンは v22.23.0 / v24.17.0 / v26.3.1。注目すべきは、このリリースに「TLSのホスト名(サーバー証明書の身元)検証をすり抜ける」種類のバグが何件も同居している点です。HTTPSの安全性は最終的に「証明書の名前と接続先の名前が一致するか」に懸かっています。今回はその一致判定が複数の経路で破れていました。

なかでも象徴的なのが、HIGH評価の CVE-2026-48618Unicodeのドット文字の扱いの違いを突いて、ワイルドカード証明書の検証を回避できるという問題です。マルチテナントSaaSで最も普通に使われる *.example.com 形式の証明書が標的になり得ます。この記事では、今回まとめて塞がれたホスト名検証バイパス系のCVEを中心に、仕組みと対処を読み解きます。

このリリースの全体像(早見表)

項目内容
公開日2026年6月18日(木)
修正CVE数12件(HIGH 2件 / 残りはMEDIUM・LOW)
対象ライン22.x(Maintenance LTS)・24.x(Active LTS)・26.x(Current)
パッチ版v22.23.0 / v24.17.0 / v26.3.1
同梱更新OpenSSL 3.5.7、nghttp2 1.69.0、llhttp 9.4.2 ほか

Node.jsはバンドルしているOpenSSLやnghttp2などの依存も同時に上げているため、TLS/HTTP2まわりの更新がまとめて入る版でもあります。アプリ側のコードを変えなくても、ランタイムを上げるだけで効く修正が多いのがこの種のリリースの特徴です。

なぜ「ホスト名の比較」がこれほど壊れるのか

HTTPSの信頼は、ざっくり言うと2段階です。

  1. 証明書チェーンが正しい認証局までたどれること(署名の検証)
  2. その証明書に書かれた名前が、いま接続しようとしている相手の名前と一致すること(身元の検証)

(1)は数学的な検証で間違えにくいのですが、(2)は「文字列としての名前が一致するか」という、人間的で曖昧な処理です。ここには大きな落とし穴があります。DNSの世界での「同じ名前」と、証明書検証コードの世界での「同じ名前」が、正規化(normalize)のルールが食い違っていると一致しなくなるのです。

今回HIGHになった CVE-2026-48618 は、まさにこの「正規化の食い違い」が原因です。アドバイザリは原因をresolver(名前解決側)とverifier(証明書検証側)のホスト名正規化の不一致と説明しており、Unicodeのドット区切り文字の扱いの差が悪用ポイントとされています。

NOTE

ドメイン名のドットは、ASCIIの .(U+002E)だけではありません。Unicodeには見た目や意味がドットに近い文字(全角のドットや、各言語のIDEOGRAPHIC FULL STOPなど)が複数あります。ある層では「これはドット扱い(ラベル区切り)」、別の層では「ただの文字」と判断されると、a.evil.example.com のような名前が、ある層では3ラベル、別の層では別のラベル数に見えてしまいます。

ワイルドカード証明書(*.example.com)は「ドットで区切られた1階層分のラベルだけ」をマッチさせるのが原則です(*.example.coma.example.com には一致するが a.b.example.com には一致しない、というルール)。ここでラベルの区切り判定がずれると、本来は一致しないはずの深い階層のホスト名が「一致する」と誤判定され、攻撃者が用意した名前に対して正規のワイルドカード証明書が通ってしまう、というのがこのバイパスの骨子です。報告者は tmeletlidis、修正は Matteo Collina によるものとアドバイザリに記載されています。

今回まとめて塞がれたホスト名検証バイパス4種

このリリースの面白い(そして怖い)ところは、ホスト名・身元の検証をすり抜けるバグが1件ではなく複数同居していた点です。仕組みの軸が少しずつ違うので並べて比べてみます。

CVE評価軸になっている食い違い影響の方向
CVE-2026-48618HIGHUnicodeドット区切りの正規化不一致ワイルドカード証明書の検証バイパス
CVE-2026-48928MEDIUMSNIの大文字小文字マッチング不整合マルチコンテキストmTLSでの認可バイパス
CVE-2026-48930MEDIUMホスト名中の埋め込みNUL文字によるC文字列切り詰め接続先(authority)の取り違え
CVE-2026-48934MEDIUMTLSセッション再利用時のservername不整合別サーバー名でのホスト身元検証バイパス

4件すべてに共通するのは、「同じ名前のはずなのに、判定する場所によって違う名前に見える」という構図です。順に見ていきます。

CVE-2026-48618(HIGH): Unicodeドットでワイルドカードを抜ける

前述のとおり、ドット区切り文字の正規化が解決側と検証側で食い違うことで、ワイルドカード証明書のラベル深さの検証を回避できます。*.example.com 証明書を使うマルチテナント構成、つまりサブドメインを動的に発行するSaaSが典型的な対象です。Node.js組み込みの身元検証に頼っている場合、アプリ側で何もしていなくてもこの判定はランタイム任せなので、影響を受けます。

CVE-2026-48928(MEDIUM): SNIの大文字小文字

TLSのSNI(Server Name Indication)で示されるホスト名は、本来大文字小文字を区別しないのがドメイン名の常識です。ところがコンテキスト(複数のTLS設定を1つのサーバーで束ねるケース)のマッチングが大文字小文字を区別してしまうと、API.example.comapi.example.com が別物として扱われ、mTLS(相互TLS)のトラスト・ポリシーがすり抜けられる余地が生まれます。サーバー側で複数のSecureContextを使い分けている構成が対象です。

CVE-2026-48930(MEDIUM): 埋め込みNUL文字

ホスト名の途中に NUL 文字(\0)を埋め込むと、内部でCの文字列として扱われる箇所がNULで切り詰められて別のホスト名に化ける、というクラシックな問題です。evil.com\0.example.com のような入力が、ある層では evil.com\0.example.com、別の層では evil.com として解釈され、接続先(authority)が静かにすり替わります。入力検証の層とリゾルバの層で扱いが違うことが原因です。

CVE-2026-48934(MEDIUM): セッション再利用での取り違え

TLSセッションを再利用して接続を高速化する際、再利用時に指定したservername(接続先ホスト名)が元のセッションと違っていても、身元検証を素通りしてしまう問題です。性能のためのセッションキャッシュが、身元検証の前提を崩してしまう典型例と言えます。

ホスト名以外のHIGH/注目CVE

ホスト名系以外にも、押さえておきたい修正があります。

  • CVE-2026-48933(HIGH): WebCryptoのDoSsubtle.encrypt() に 2GiB の倍数となる入力を渡すと整数オーバーフローでプロセスがクラッシュします。大きなバイナリを暗号化する経路を外部入力に晒しているサービスは要注意です。報告は erichen、修正は Filip Skokan。
  • CVE-2026-48615(MEDIUM): プロキシ認証情報の漏えいERR_PROXY_TUNNEL エラーにプロキシ認証情報が含まれ、ログやエラーメッセージ経由で漏れる可能性があります。
  • CVE-2026-48619(MEDIUM): HTTP/2のORIGINフレームでメモリ枯渇 — サーバーが無制限にORIGINフレームを送るとクライアント側のメモリが青天井に増えOOMにつながります。
  • Permission Model関連(LOW複数)process.report.writeReport()FileHandle.utimes() 経由で、--permission の制限を一部すり抜けられる問題が修正されています。実験的機能ですが、サンドボックス前提で使っているなら無視できません。

いま実務でやること

やるべきことはシンプルですが、優先度を間違えないことが大切です。

  1. まずランタイムを上げるnode -v で現在のラインを確認し、v22.23.0 / v24.17.0 / v26.3.1 以上へ。LTSラインも全部対象なので「古いLTSだから安全」ではありません。
  2. コンテナイメージとCIのベースを更新するFROM node:22 のようなタグはパッチを自動で拾える場合もありますが、固定タグ(node:24.16.0 など)で運用しているなら明示的に上げます。サーバーだけでなくCIランナーやLambdaのランタイムも忘れずに。
  3. ワイルドカード証明書 + Node組み込みのTLS検証に依存している箇所を洗い出すhttps.requesttls.connect、外部APIへのHTTPSクライアント、サービス間通信(mTLS)などが該当します。*.example.com 系を多用するマルチテナント構成は CVE-2026-48618 の直撃対象です。
  4. 自前でホスト名検証を実装している箇所(checkServerIdentity の上書きなど)を疑う。今回の根っこは「正規化の食い違い」です。独自実装はランタイムの修正が効かないので、Unicode正規化・大文字小文字・NUL・ラベル深さの扱いを自分で見直す必要があります。

WARNING

rejectUnauthorized: falsecheckServerIdentity を空関数で潰している既存コードがあると、今回の修正をいくら当てても意味がありません。アップデートついでに、検証を無効化している箇所がないかを必ず棚卸ししてください。

サプライチェーン経由の侵入が話題になりがちですが(Axiosのnpm汚染のような事例)、今回のようにランタイムそのもののTLS検証ロジックが破れるタイプは、依存ロックやSBOMでは防げません。ランタイムの定期更新を運用に組み込んでおくことが唯一の対策です。Node.jsの年次リリーススケジュールを押さえ、LTSの追従を仕組み化しておきましょう。

まとめ

  • 2026年6月18日のNode.jsセキュリティリリースは、全アクティブライン(22/24/26)で12件のCVEを一斉修正。HIGHは2件。
  • パッチ版は v22.23.0 / v24.17.0 / v26.3.1。LTSラインも全て対象なので、古いLTSでも更新が必要。
  • 目玉はTLSホスト名検証バイパスの集中修正。Unicodeドット(CVE-2026-48618 / HIGH)、SNI大文字小文字(CVE-2026-48928)、埋め込みNUL(CVE-2026-48930)、セッション再利用(CVE-2026-48934)と、原因は違えど「同じ名前が場所により違って見える」構図で共通している。
  • ワイルドカード証明書 + Node組み込みTLS検証に依存するマルチテナントSaaSが最も影響を受けやすい。
  • 対策はランタイム更新が基本。加えて、検証を無効化・自前実装している箇所の棚卸しを忘れずに。

参考リンク

Node.jsが年1回のメジャーリリースへ - Node 27からの新スケジュールとLTSの考え方

Node.jsが年1回のメジャーリリースへ - Node 27からの新スケジュールとLTSの考え方

7

Node.js が 2026年3月の公式発表でリリーススケジュールを変更します。Node 27(2027年)から、メジャーは年1回(毎年4月)に集約され、奇数/偶数の区別を廃止して全リリースが LTS 対象に。早期テスト用の Alpha チャンネル新設、総サポート期間の36か月化など、新旧スケジュールの違いと、Node 26 / Node 27 の位置づけ、運用への影響を Node.js 公式ブログを一次ソースに整理します。

セマンティックバージョニングと package.json のバージョン指定 - ^ と ~ の違い、0.x の罠

セマンティックバージョニングと package.json のバージョン指定 - ^ と ~ の違い、0.x の罠

8

セマンティックバージョニング(semver)と npm のバージョン指定を実務目線で整理します。MAJOR.MINOR.PATCH の意味、0.y.z(初期開発版)の特別扱い、プレリリースとビルドメタデータ、そしてキャレット ^ とチルダ ~ が許可する範囲の違い、^0.2.3 が ~ と同じになる 0.x の罠、package.json と package-lock.json の役割分担、npm install / ci / update の違いまで、semver.org・npm 公式・node-semver を一次ソースにまとめます。