
JWTの署名検証が、鍵が空っぽでも通ってしまう。そんな初歩的な、しかし見落とされ続けてきた欠陥が、2026年10月に複数言語のJWT/JOSEライブラリで相次いでCVE化している。Python向けに広く使われるAuthlibもその一つで、CVE-2026-114616として10月22日(日本時間23日未明)に公開された。深刻度はCVSS 7.4。影響範囲はAuthlib 1.7.2以下(1.7.2が最新リリースだった)で、修正は1.9.1。 問題の核心は暗号が破られたことではなく、鍵の長さの下限チェックが存在しないことだ。HS256/HS384/HS512はHMACで署名する。HMACは鍵と本文からハッシュを計算するが、鍵が空(長さ0のバイト列や空文字列)でも計算自体は成立してしまう。そして空鍵のHMACは、本文さえ分かれば誰でも同じ値を再現できる決定的な関数になる。つまり検証側が空の鍵を受け入れてしまえば、攻撃者は秘密を一切知らなくても任意のクレームを持つトークンに正しい署名を付けられる。管理者ロールでも何でも偽造し放題になる。 現実の引き金は「アプリの秘密鍵取得が、実行時に空を返しうる」構成だ。環境変数の既定値を空文字列にしている、設定テーブルの既定値が空、鍵リゾルバが見つからない時に空を返す、といったよくある実装がそのまま踏み台になる。AuthlibはOAuth 2.0のリソースサーバやOIDCのリライングパーティを作るための土台であり、トークン検証こそが主戦場なので、空鍵が通る経路は現実の露出になりうる。 これが一つのライブラリに限った話でないのが今回の重要点だ。同じ空HMAC鍵の欠陥が言語をまたいで報告されており、報告者はこれを cross-language empty-HMAC-key family と呼んでいる。npmのfast-jwtがCVE-2026-44351(修正6.2.4)、RubyのjwtがCVE-2026-45363(修正2.10.3および3.2.0)、同じ作者のPythonライブラリjoserfcがCVE-2026-49852(修正1.6.8)、そしてAuthlibがCVE-2026-114616。設計者が別々でも、HMAC鍵の最小長を検証しないという同じ穴に全員が落ちている。 私は実際に手元のLinuxマシン(8 vCPU、Debian 13.7、Python 3.13.5、Node.js 22.14.0)で検証した。まずAuthlib 1.7.2に、空のバイト列を鍵としてalg=HS256、ペイロードに管理者ロールを入れたトークンを署名させると、素直に発行された。それを同じ空鍵でAuthlibに検証させると、当然のように通る。次が肝心で、Authlibを一切使わず、Python標準のhmacモジュールだけで同じヘッダとペイロードに空鍵のHMACを計算したところ、Authlibが出したトークンと1バイトも違わない署名が得られ、その自作トークンもAuthlibの検証を通過した。秘密を知らない第三者が偽造できることの実証だ。 修正版のAuthlib 1.9.1では、空のバイト列も空文字列も ValueError(oct key material must not be empty)で弾かれ、署名も検証も拒否される。ここまでは期待通り。ただし独自に確かめて意外だったのは、わずか1バイト(8ビット)の鍵は1.9.1でも素通りで署名できてしまうことだ。つまりこの修正は完全に空の鍵だけを塞ぐもので、短すぎる=事実上総当たり可能な弱鍵は依然として受け入れる。推奨される後継ライブラリjoserfc(検証環境では1.7.7)も同様で、空鍵は拒否するものの、112ビット未満の鍵に対しては SecurityWarning を出すだけで署名自体は成立してしまった。 言語をまたいだ挙動の差も見えた。npmのfast-jwtは、鍵に直接空文字列を渡すとオプション検証の段階で FAST_JWT_INVALID_OPTION として拒否する。ところが鍵を非同期リゾルバ(空文字列を返す関数)として渡すと、その検証をすり抜けて署名も検証も通ってしまう。検証環境のfast-jwt 5.0.5で管理者トークンの偽造が成立することを確認し、最新の6.3.6では同じ経路が FAST_JWT_INVALID_KEY で塞がれていることも確認した。CVEの「async key resolver経由」という記述そのものの挙動だ。 運用面での注意点として、ディストリ同梱版はまだ古い。Debianのセキュリティトラッカーを確認した時点では、python-authlibはbookworm(1.2.0)、trixie(1.6.0)、sid(1.7.2-2)いずれも vulnerable 表示のままだった。pipで最新を入れているつもりでも、OS側のパッケージ経由で古いAuthlibが混在していないか要確認だ。 まとめると、これは派手なゼロデイではなく、JWTライブラリ全体に横たわる鍵の下限を検証しないという設計上の油断が、複数言語で一斉に表面化した事例だ。利益を受けるのは、空になりうる秘密を一度でも通してしまう構成を抱えた全てのトークン検証側。本当の防御はバージョンを上げるだけでなく、鍵リゾルバが絶対に空や極端に短い値を返さないことを自分で保証し、できればHMAC鍵は十分な長さ(最低でも112ビット、実務的には256ビット以上)を強制することにある。修正版ですら1バイト鍵で署名できてしまう以上、ライブラリ任せにしない姿勢が要る。 一次情報は、Authlibアドバイザリ GHSA-8m4g-j4wp-wgcg、CVE-2026-114616(NVDおよびOSV)、Authlib 1.9.1 チェンジログ(2026-10-14)、Debianセキュリティトラッカー CVE-2026-114616。関連CVEは CVE-2026-44351(fast-jwt)、CVE-2026-45363(ruby-jwt)、CVE-2026-49852(joserfc)。該当コードは GitHub authlib/authlib のauthlib/jose/rfc7518配下、兄弟実装は GitHub nearform/fast-jwt #セキュリティ #JWT
