GitHub Security Advisory: GHSA-7432-952r-cw78
Package: authlib (PIP)
Severity: HIGH (CVSS 0.0)
CWE: CWE-203: Observable Discrepancy, CWE-327: Use of a Broken or Risky Cryptographic Algorithm
Vulnerable versions: <= 1.6.8
Patched in: 1.6.9

Summary: Authlib Vulnerable to JWE RSA1_5 Bleichenbacher Padding Oracle

Details:
## 1. Executive Summary

A cryptographic padding oracle vulnerability was identified in the Authlib Python library
concerning the implementation of the JSON Web Encryption (JWE) `RSA1_5` key management
algorithm. Authlib registers `RSA1_5` in its default algorithm registry without requiring
explicit opt-in, and actively destroys the constant-time Bleichenbacher mitigation that
the underlying `cryptography` library implements correctly.

When `cryptography` encounters an invalid PKCS#1 v1.5 padding, it returns a randomized
byte string instead of raising an exception — the correct behavior per RFC 3218 §2.3.2.
Authlib ignores this contract and raises `ValueError('Invalid "cek" length')` immediately
after decryption, before reaching AES-GCM tag validation. This creates a clean, reliable
**Exception Oracle**:

- **Invalid padding** → `cryptography` returns random bytes → Authlib length check fails
  → `ValueError: Invalid "cek" length`
- **Valid padding, wrong MAC** → decryption succeeds → length check passes → AES-GCM
  fails → `InvalidTag`

**This oracle is active by default in every Authlib installation without any special
configuration by the developer or the attacker.** The three most widely used Python web
frameworks — Flask, Django, and FastAPI — all expose distinguishable HTTP responses for
these two exception classes in their default configurations, requiring no additional
setup to exploit.

**Empirically confirmed on authlib 1.6.8 + cryptography 46.0.5:**
```
[PADDING INVALIDO]     ValueError: Invalid "cek" length
[PADDING VALIDO/MAC]   InvalidTag
```

---

## 2. Technical Details & Root Cause

### 2.1 Vulnerable Code

**File:** `authlib/jose/rfc7518/jwe_algs.py`

```python
def unwrap(self, enc_alg, ek, headers, key):
    op_key = key.get_op_key("unwrapKey")

    # cryptography implements Bleichenbacher mitigation here:
    # on invalid padding it returns random bytes instead of raising.
    # Empirically confirmed: returns 84 bytes for a 2048-bit key.
    cek = op_key.decrypt(ek, self.padding)

    # VULNERABILITY: This length check destroys the mitigation.
    # cryptography returned 84 random bytes. len(84) * 8 = 672 != 128 (A128GCM CEK_SIZE).
    # Authlib raises a distinct ValueError before AES-GCM is ever reached.
    if len(cek) * 8 != enc_alg.CEK_SIZE:
        raise ValueError('Invalid "cek" length')   # <- ORACLE TRIGGER

    return cek
```

### 2.2 Root Cause — Active Mitigation Destruction

`cryptography` 46.0.5 implements the Bleichenbacher mitigation correctly at the library
level. When PKCS#1 v1.5 padding validation fails, it does not raise an exception.
Instead it returns a randomized byte string (empirically observed: 84 bytes for a
2048-bit RSA key). The caller is expected to pass this fake key to the symmetric
decryptor, where MAC/tag validation will fail in constant time — producing an error
indistinguishable from a MAC failure on a valid padding.

Authlib does not honor this contract. The length check on the following li