PythonのAuthlibに、署名が付いていないJWSを「検証済み」として返してしまう脆弱性が公表されました。CERT/CC が 2026年9月28日に公表し、JPCERT/CC が 9月29日に JVNVU#99151548 として転載しています。CVE番号は CVE-2026-96760 です。
攻撃者は鍵も署名も持たずに、好きな内容のペイロードを「検証済み」として通せます。CERT/CC は、身元の詐称による認証回避、権限昇格、マイクロサービス間の署名付きメッセージの偽装、スコープやロールといった認可情報の偽造を挙げています。
2026年9月29日時点で、修正版は出ていません。CERT/CC は理由も書いており、「ベンダーと連絡が取れず、この脆弱性の調整ができなかった。本稿の執筆時点で公式のパッチは提供されていない」としています。そして後で詳しく書きますが、CVEが「1.7.2以下」と書いている一方で、それより新しい 1.8.0 でも該当コードは1文字も変わっていません。
一方で、通る経路は限られています。
JWSの「JSON Serialization」を受け取る処理だけが対象で、Authlib の JWT の `decode()` は影響を受けません。まず自分がどちらなのかを切り分けてください。
何が起きるのか
NVD に載っている説明をそのまま書きます。
「Authlib(v1.7.2以下)には署名検証の回避の脆弱性がある。`JsonWebSignature.deserialize_json()` は JSON Serialization の JWS オブジェクトを受け取り、署名を確認せず、暗号鍵も要求せずに、ペイロードを検証済みとして返す」
CERT/CC はもう少し具体的で、「`signatures` が空の配列である JWS オブジェクトを受け入れ、ペイロードを検証成功として扱う」と書いています。
★該当するコードを読むと1行で分かる
当サイトで GitHub の該当ファイルを直接確認しました。`authlib/jose/rfc7515/jws.py` の `deserialize_json()` の終盤が次のようになっています。
headers = []
is_valid = True
for header_obj in obj["signatures"]:
jws_header, valid = self._validate_json_jws(
payload_segment, payload, header_obj, key
)
headers.append(jws_header)
if not valid:
is_valid = False
rv = JWSObject(headers, payload, "json")
if is_valid:
return rv
raise BadSignatureError(rv)`is_valid` の初期値が `True` で、そのあとに `signatures` をループしています。
`signatures` が空の配列なら、ループは1回も回りません。つまり `_validate_json_jws()` が一度も呼ばれず、`is_valid` は `True` のまま `return rv` に到達します。署名の確認も鍵の要求も、どこにも発生しません。
★1.8.0 でも直っていない
CVEもCERT/CCも影響範囲を「1.7.2以下」と書いていますが、これは狭すぎます。当サイトで確認した結果を書きます。
`authlib/jose/rfc7515/jws.py` を v1.7.2・v1.8.0・master の3つで取得したところ、3つともファイルが完全に同一でした(SHA-256が一致)。つまり1.8.0 はこの問題の修正版ではありません。
GitHub のリリース一覧でも、最新は 2026年8月30日の v1.8.0 で、CERT/CC の公表(9月28日)以降のリリースはありません。CERT/CC の「パッチは提供されていない」という記述と整合します。
「1.7.2以下」という表記を見て 1.8.0 なら安全だと判断しないでください。当サイトが確認できたのはコードが同一であることまでで、1.8.0 で実際に攻撃が成立するかまでを検証したわけではありません。それでも、修正されていないコードを安全側に数える理由はありません。
自分が影響を受けるかの切り分け
Authlib を入れている=全部危ない、ではありません。次の順で確認してください。
- ✓`JsonWebSignature.deserialize_json()` を直接呼んでいるかを探す。呼んでいれば該当する
- ✓★`JsonWebSignature.deserialize()` に、外部から来る文字列を渡していないかを探す。CERT/CC も「Authlibで JWS を読み込む両方の方法が影響を受ける」として、`deserialize_json(...)` と `deserialize('{"payload":"...","signatures":[]}', key=None)` の2つを並べて挙げています。この関数は渡された値が `dict` の場合、または `{` で始まり `}` で終わる文字列の場合に、自動で `deserialize_json()` へ振り分けます。
つまり形式を選ぶのは攻撃者側です。compact形式のつもりでも、`{...}` を送られれば脆弱な経路に入ります - ✓`deserialize_compact()` だけを呼んでいるなら、この経路は通りません
- ✓Authlib の JWT を `jwt.decode()` で使っているだけなら影響を受けません。JWT側の実装は `deserialize_compact()` を呼んでおり、`deserialize_json()` を呼んでいません
パッチが出るまでにできること
修正版が無いので、コード側で塞ぐしかありません。以下は公式が示した回避策ではなく、上で確認したコードの挙動から導いたものです。自分の環境で影響を確かめてから適用してください。
- ✓`deserialize()` をやめて `deserialize_compact()` を明示的に呼ぶ。形式の自動判定をなくせば、攻撃者が JSON形式を選べなくなります
- ✓JSON Serialization を受け付ける必要があるなら、検証の前に `signatures` が空でないことを自分で確かめる。空配列、またはキーそのものが無い入力を拒否します
- ✓鍵を渡さずに呼んでいないかを確認する。`deserialize_json()` のドキュメント文字列には「鍵が与えられない場合は署名検証なしで dict を返す」と元から書かれています。これは脆弱性とは別に、意図せず使うと危険な仕様です
- ✓GitHub のリリース一覧を監視し、修正版が出たら上げる。CERT/CC も現時点の推奨をこれにしています
★CVSSスコアはまだ付いていません
この記事にはCVSSスコアを書いていません。存在しないからです。確認した結果を書きます。
CVE.orgのレコード(採番元はCERT/CC)には、CVSSの `metrics` そのものが載っていません。NVD側は `metrics` が空のオブジェクトで、`vulnStatus` は `Received`(受領済み・未解析)です。
CVEレコード自体は公開済み(`state: PUBLISHED`。ID予約が2026年9月23日、公開が9月28日)なので、番号が存在しないという意味ではありません。
数字が無いことを「大したことない」と読み替えないでください。単に評価がまだ済んでいないだけです。
そもそも `authlib.jose` は非推奨です
影響範囲を調べているときに気づいた点も書いておきます。
`authlib/jose/__init__.py` は読み込み時に非推奨の警告を出します。メッセージは「authlib.jose module is deprecated, please use joserfc instead.」で、そのあとに「It will be compatible before version 2.0.0.」という一文が続きます。
これは「2.0.0 より前までは互換を保つ」という意味で、2.0.0 で削除すると書かれているわけではありません。(`authlib/deprecate.py` が `version` 引数からこの文を組み立てています)
今回の脆弱性はこの非推奨モジュールの中にあります。急ぎの対処とは別に、移行先が公式に示されていることは判断材料になります。
同僚に共有するならこの3行
- ▸Authlib に署名なしのJWSを「検証済み」として返す脆弱性(CVE-2026-96760)。鍵も署名も不要で、認可情報を偽造できる
- ▸2026年9月29日時点で修正版なし。CVEは「1.7.2以下」と書いているが、1.8.0 でも該当ファイルは同一で直っていない
- ▸影響するのはJWSのJSON形式を受け取る経路だけ。`jwt.decode()` は対象外。`deserialize()` は攻撃者に形式を選ばせるので `deserialize_compact()` を明示する
根拠にしたページ
- JVNVU#99151548:Authlibライブラリにおける署名検証が回避される脆弱性(2026年9月29日公開)↗
- CERT/CC VU#762428:Authlib library contains a signature-verification bypass vulnerability(空のsignatures配列・パッチ未提供・報告日)↗
- NVD:CVE-2026-96760(脆弱性の説明。vulnStatusはReceivedでスコア未付与)↗
- CVE.org:CVE-2026-96760(採番元はCERT/CC。CVSSのmetricsメンバーが無い)↗
- GitHub:authlib/jose/rfc7515/jws.py(v1.8.0)— 本文に引用した deserialize_json() のコード↗
- GitHub:Authlib のリリース一覧(最新はv1.8.0・2026年8月30日)↗
- PyPI:Authlib(各版の公開日)↗
