TL;DR

Authlib's JsonWebSignature.deserialize_json() returned the payload of a JWS JSON Serialization object as verified when its signatures array was empty, so a relying party that fed it untrusted tokens accepted attacker-written claims with no key involved (CVE-2026-96760; CISA-ADP 9.8, GitHub 9.1). The CERT/CC record from 2026-09-28 says "1.7.2 and below", but 1.8.0 (PyPI 2026-08-30) was also vulnerable; the fix is PR #938 in 1.9.0 (PyPI 2026-10-14), whose release notes carry no security wording. Upgrade to 1.9.0 or later and check whether any token your service accepts is parsed through the JSON-serialization path.

What happened

  • 2026-08-21. CERT/CC notified the vendor (VU#762428, "Vendor Notified" field). The note says no statement was received and the vendor could not be reached to coordinate.
  • 2026-08-30. Authlib 1.8.0 reached PyPI, still carrying the bug.
  • 2026-09-28. CERT/CC published VU#762428 and CVE-2026-96760 as the CNA: JsonWebSignature.deserialize_json() accepts a JWS object whose signatures list is empty and "returns the payload as successfully verified without checking for a signature and without requiring a cryptographic key"; the deserialize() wrapper reaches the same code. Affected "up to and including 1.7.2"; fixed version "None". CISA's ADP added CVSS 3.1 9.8. The GitHub Advisory Database mirrored it the same day as GHSA-6m87-8wg6-hh8w with < 1.9.0 and no patched version.
  • 2026-10-05. Per the advisory now on the vendor repository, the only fix at that date was the unmerged pull request #938, and the GitHub record had no machine-readable range, so OSV-based scanners reported 1.8.0 as clean.
  • 2026-10-14. GHSA-6v38-4h7w-rj9h was published on authlib/authlib (Critical, CVSS 3.1 9.1, AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N, CWE-347) under the title "Signature verification bypass (CVE-2026-96760) is live in the current release 1.8.0, which every published record excludes". Its text: "This is already public. What is new is the version range." Root cause as stated there: the validity flag starts true and is only set false inside the loop over signatures, so an empty array never fails. Credits: zer0d4y5, uziii2208, nguyenminhtuan28. The same day Authlib 1.9.0 and 1.9.1 reached PyPI; the 1.9.0 release notes list "Fix empty signatures validation in JWS JSON deserialization" (PR #938) beside four OAuth validation fixes, with no CVE and no security label.
  • 2026-10-27. The database reviewed GHSA-6v38-4h7w-rj9h (affected <= 1.8.0, patched 1.9.0) and withdrew GHSA-6m87-8wg6-hh8w as a duplicate. The row appeared on the reviewed-critical pip listing that morning.

Three affected ranges exist, and only one is right for an installed app. The CNA says 1.7.2 and below; the withdrawn mirror said below 1.9.0; the live vendor-repository advisory says 1.8.0 and below with 1.9.0 patched. The registry settles it: 1.8.0 was published nine days after vendor notification and before the fix, so a scanner keyed to the CNA range misses it. Treat anything below 1.9.0 as affected.

What a reader is exposed to. The compact serialization (a.b.c tokens, the common OAuth and OIDC path) is not the path the records describe; the bypass is in the JSON Serialization (RFC 7515 section 7.2) parser. A service that accepts JSON-form JWS from clients, partners or a microservice peer, or that passes untrusted input into deserialize() without knowing which form arrives, can be handed a payload with forged sub, roles or scopes. CERT/CC lists authentication bypass, forged inter-service messages and forged permissions as the consequences.

Am I affected?

pip show authlib 2>/dev/null | grep -i ^version      # below 1.9.0 is affected
grep -rn "deserialize_json\|JsonWebSignature\|\.deserialize(" --include=*.py . | grep -v site-packages
  • A version at or below 1.8.0 is affected. The CNA's "1.7.2 and below" undercounts by one release.
  • The grep tells you whether the JSON-serialization parser is reachable from input you do not control. If every token you verify is compact-form and comes from jwt.decode() with a key, the records describe a path you may not be using; upgrade anyway, because the 1.9.0 notes also tighten OAuth key, scope, audience, nonce and JAR validation.

If you are affected

  1. Upgrade to authlib>=1.9.0 and redeploy; the fix is in the parser, not in configuration.
  2. If untrusted JSON-form JWS reached a vulnerable version, audit the identities those tokens asserted against your own records for the window since the service first accepted them. Auditing a vibe-coded repo and if your webapp was compromised.

Prevention

  • Pin and audit auth libraries separately from the rest of the tree, because a fix release here carried no security wording and an aggregator range excluded a vulnerable version for six weeks. Package vetting checklist.
  • Verify tokens with an explicit key and algorithm allowlist and reject any JWS whose signature list is empty before handing it to a library.

Sources