GitHub Security Advisory: GHSA-m344-f55w-2m6j
Package: authlib (PIP)
Severity: HIGH (CVSS 0.0)
CWE: CWE-354: Improper Validation of Integrity Check Value, CWE-573: Improper Following of Specification by Caller
Vulnerable versions: <= 1.6.8
Patched in: 1.6.9

Summary: Authlib: Fail-Open Cryptographic Verification in OIDC Hash Binding

Details:
## 1. Executive Summary

A critical library-level vulnerability was identified in the **Authlib** Python library concerning the validation of OpenID Connect (OIDC) ID Tokens. Specifically, the internal hash verification logic (`_verify_hash`) responsible for validating the `at_hash` (Access Token Hash) and `c_hash` (Authorization Code Hash) claims exhibits a **fail-open** behavior when encountering an unsupported or unknown cryptographic algorithm. 

This flaw allows an attacker to bypass mandatory integrity protections by supplying a forged ID Token with a deliberately unrecognized `alg` header parameter. The library intercepts the unsupported state and silently returns `True` (validation passed), inherently violating fundamental cryptographic design principles and direct OIDC specifications.

---

## 2. Technical Details & Root Cause

The vulnerability resides within the `_verify_hash(signature, s, alg)` function in `authlib/oidc/core/claims.py`:

```python
def _verify_hash(signature, s, alg):
    hash_value = create_half_hash(s, alg)
    if not hash_value:        # ← VULNERABILITY: create_half_hash returns None for unknown algorithms
        return True            # ← BYPASS: The verification silently passes
    return hmac.compare_digest(hash_value, to_bytes(signature))
```

When an unsupported algorithm string (e.g., `"XX999"`) is processed by the helper function `create_half_hash` in `authlib/oidc/core/util.py`, the internal `getattr(hashlib, hash_type, None)` call fails, and the function correctly returns `None`. 

However, instead of triggering a `Fail-Closed` cryptographic state (raising an exception or returning `False`), the `_verify_hash` function misinterprets the `None` return value and explicitly returns `True`. 

Because developers rely on the standard `.validate()` method provided by Authlib's `IDToken` class—which internally calls this flawed function—there is **no mechanism for the implementing developer to prevent this bypass**. It is a strict library-level liability.

---

## 3. Attack Scenario

This vulnerability exposes applications utilizing Hybrid or Implicit OIDC flows to **Token Substitution Attacks**.

1. An attacker initiates an OIDC flow and receives a legitimately signed ID Token, but wishes to substitute the bound Access Token (`access_token`) or Authorization Code (`code`) with a malicious or mismatched one.
2. The attacker re-crafts the JWT header of the ID Token, setting the `alg` parameter to an arbitrary, unsupported value (e.g., `{"alg": "CUSTOM_ALG"}`).
3. The server uses Authlib to validate the incoming token. The JWT signature validation might pass (or be previously cached/bypassed depending on state), progressing to the claims validation phase.
4. Authlib attempts to validate the `at_hash` or `c_hash` claims. 
5. Because `"CUSTOM_ALG"` is unsupported by `hashlib`, `create_half_hash` returns `None`.
6. Authlib's `_verify_hash` receives `None` and silently returns `True`.
7. **Result:** The application acce