Authlib < 1.9.0: Empty-Signature JWS Bypass Lets Attackers Forge Verified Payloads
What happened
A GitHub Security Advisory (GHSA-6v38-4h7w-rj9h, tracked as CVE-2026-96760) reports that authlib versions prior to 1.9.0 contain a signature verification bypass in JsonWebSignature.deserialize_json(). According to the advisory, the JWS JSON Serialization deserializer in authlib/jose/rfc7515/jws.py initializes a validity flag to True before any signatures are checked, and only flips it to False inside a loop over the object's signatures array. If an attacker submits a JWS JSON object with an empty signatures array, the loop body never executes, the flag stays True, and the payload is returned as "verified" — without a signature ever being examined and without any key material being consulted.
The advisory includes a reproduction showing this behavior on authlib 1.8.0: a forged payload with signatures: [] is accepted whether or not a real key is supplied, while the same library correctly rejects tampered signatures or a missing signatures member entirely — indicating the bug is specific to the empty-array case. The advisory also notes that joserfc, the library authlib's own deprecation warning points users toward, does not exhibit this behavior on the equivalent input.
Why it matters for defenders
Per the advisory, any relying party that calls JsonWebSignature.deserialize_json() on attacker-influenced input is affected. The CVSS score given is 9.1, and exploit status is listed as proof-of-concept public, meaning working exploitation code is already available. Where the deserialized payload carries identity or authorization claims (session tokens, SSO assertions, federation messages), this is described as a complete authentication bypass achievable by an unauthenticated remote caller with no key material — a deployment can appear fully functional (genuine signed objects still validate correctly) while forged, signature-less objects are silently accepted alongside them.
Who's affected
- Python services using
authlib(pip package) prior to 1.9.0 - Specifically, any code path that calls
JsonWebSignature.deserialize_json()on JWS JSON Serialization input from an untrusted or external source
What defenders should do now
- Inventory services for
authlibusage and check the installed version; upgrade to 1.9.0 or later wheredeserialize_json()is used, per the advisory. - Identify and audit any code paths that pass externally-supplied JWS JSON Serialization objects into
deserialize_json(), particularly where the result feeds authentication or authorization decisions. - As a hunting angle, review application or API logs for incoming JWS JSON objects with an empty or missing
signaturesarray, which is anomalous for legitimately issued tokens. - As a stopgap where upgrading isn't immediately possible, consider validating that
signaturesis non-empty before passing objects to the deserializer, or evaluate migrating tojoserfc, which the advisory states handles this case correctly. - Treat this as a supply-chain-style exposure: the vulnerable code path can be several layers removed from application code, so dependency scanning alone may not surface affected call sites — trace actual usage of the deserialization method.
Developing intel
This is based on a same-day GitHub Security Advisory; details may be refined as the project and downstream consumers respond. For the full technical writeup, reproduction steps, and the proposed fix (PR #938 referenced in the advisory), see the original GHSA-6v38-4h7w-rj9h advisory.