---
title: "Authlib flaw: an empty signature list passes any JWS, update to 1.9.0"
description: "Authlib up to 1.8.0 accepts a JWS in JSON form with an empty signatures list and returns its payload as verified, with no check and no key. The fix is in 1.9.0."
url: https://ihsanalapsi.dev/articles/authlib-jws-empty-signatures
lang: en
date: 2026-10-29
updated: 2026-10-29
tags: ["App security", "Security updates"]
author: Ihsan Alapsi (إحسان العبسي)
---
# Authlib flaw: an empty signature list passes any JWS, update to 1.9.0

If your Python project uses Authlib to verify JWS tokens that come from outside, there is a critical flaw that lets anyone send you a payload with no signature, and the library returns it as if it were signed. Here is how to tell whether your code is affected and how to fix it.

## What is the Authlib flaw?

The Authlib flaw is that `JsonWebSignature.deserialize_json()` accepts a JWS in JSON form whose `signatures` list is empty, and returns the payload as verified, with no signature check and no key required.

A JWS is a payload (such as a user's details or permissions) plus a signature that proves who wrote it. Its JSON form allows more than one signature on the same payload, which is why the signatures sit in a list.

The advisory in the GitHub Advisory Database is GHSA-6v38-4h7w-rj9h, and the flaw is CVE-2026-96760.

It is rated critical: 9.1 on CVSS 3.1.

## Why does an empty signature list pass?

The reason is that a "valid" flag in the code starts as true and only turns false inside a loop over the signatures. When the list is empty, the loop never runs, so the flag stays true and the payload comes back as verified.

The advisory gives an example: JSON with a payload and `"signatures": []`. On Authlib 1.8.0 the library accepted it, even when the code passed a real key. A corrupted signature, on the other hand, was rejected as it should be.

## Is my code affected?

Your code is affected if your Authlib version is 1.8.0 or older and you call `deserialize_json()` on a JWS you did not produce.

The advisory says this is where the risk is: if the payload carries the user's identity or permissions, an attacker writes whatever they want and gets in without signing in and without a key.

Pay attention to 1.8.0 in particular. The Authlib advisory itself says the flaw was already public and what is new is the version range: the published records left 1.8.0 out of the affected versions. So if you checked your project before and it came out "clean" on 1.8.0, check it again.

If forged tokens are your concern, we wrote earlier about [the Postiz flaw that lets a user take over a whole organisation with a forged token](/articles/postiz-forged-token-takeover).

## How do you fix it?

Update Authlib to 1.9.0. The release notes include the fix for empty signatures in JWS JSON deserialization, along with other JOSE and OAuth validation fixes.

```bash
pip install --upgrade "authlib>=1.9.0"
pip show authlib
```

If you cannot update today, reject any JWS with an empty signatures list yourself before it reaches the library. This is the same fix the advisory suggests, only in your own code:

```python
import json

def require_signatures(raw: str) -> str:
    data = json.loads(raw)
    if not data.get("signatures"):
        raise ValueError("JWS without signatures")
    return raw
```

This is a stopgap. The update is still the fix.

If you are updating Python itself as well, see [the October Python security releases](/articles/python-october-2026-security-releases).

## Where do you start now?

Start with your version and the places where you verify tokens.

1. Run `pip show authlib` and check whether the version is 1.8.0 or older.
2. Search your code for `deserialize_json` and see who sends the input.
3. Update to 1.9.0, or add the empty-signatures check until you can.

If you want someone to test the sign-in and token flow of your platform the way an attacker would, that is what [Muhassan](/muhassan) does.

All our app security articles are in one place: [App security](/articles?tag=app-security).

## FAQ

**Does the attacker need the key?**

No. According to the advisory, the payload comes back as verified with no signature check and no key required.

**I thought 1.8.0 was not affected. Why?**

The Authlib advisory says the flaw was already public and what is new is the version range: earlier published records left 1.8.0 out. Affected versions now run up to 1.8.0, and the fix is in 1.9.0.

**If I do not call deserialize_json, am I safe?**

The advisory names deserialize_json only. Update to 1.9.0 anyway, because the same release has other JOSE and OAuth validation fixes.
