GitHub Security Advisory: GHSA-9ggr-2464-2j32
Package: authlib (PIP)
Severity: HIGH (CVSS 7.5)
CWE: CWE-345: Insufficient Verification of Data Authenticity, CWE-863: Incorrect Authorization
Vulnerable versions: < 1.6.4
Patched in: 1.6.4

Summary: Authlib: JWS/JWT accepts unknown crit headers (RFC violation → possible authz bypass)

Details:
## Summary
Authlib’s JWS verification accepts tokens that declare unknown critical header parameters (`crit`), violating RFC 7515 “must‑understand” semantics. An attacker can craft a signed token with a critical header (for example, `bork` or `cnf`) that strict verifiers reject but Authlib accepts. In mixed‑language fleets, this enables split‑brain verification and can lead to policy bypass, replay, or privilege escalation.

## Affected Component and Versions
- Library: Authlib (JWS verification)
- API: `authlib.jose.JsonWebSignature.deserialize_compact(...)`
- Version tested: 1.6.3
- Configuration: Default; no allowlist or special handling for `crit`

## Details
RFC 7515 (JWS) §4.1.11 defines `crit` as a “must‑understand” list: recipients MUST understand and enforce every header parameter listed in `crit`, otherwise they MUST reject the token. Security‑sensitive semantics such as token binding (e.g., `cnf` from RFC 7800) are often conveyed via `crit`.

Observed behavior with Authlib 1.6.3:
- When a compact JWS contains a protected header with `crit: ["cnf"]` and a `cnf` object, or `crit: ["bork"]` with an unknown parameter, Authlib verifies the signature and returns the payload without rejecting the token or enforcing semantics of the critical parameter.
- By contrast, Java Nimbus JOSE+JWT (9.37.x) and Node `jose` v5 both reject such tokens by default when `crit` lists unknown names.

Impact in heterogeneous fleets:
- A strict ingress/gateway (Nimbus/Node) rejects a token, but a lenient Python microservice (Authlib) accepts the same token. This split‑brain acceptance bypasses intended security policies and can enable replay or privilege escalation if `crit` carries binding or policy information.

## Proof of Concept (PoC)
This repository provides a multi‑runtime PoC demonstrating the issue across Python (Authlib), Node (`jose` v5), and Java (Nimbus).

### Prerequisites
- Python 3.8+
- Node.js 18+
- Java 11+ with Maven

### Setup

Enter the directory **authlib-crit-bypass-poc** & run following commands.
```bash
make setup
make tokens
```

### Tokens minted
- `tokens/unknown_crit.jwt` with protected header:
  `{ "alg": "HS256", "crit": ["bork"], "bork": "x" }`
- `tokens/cnf_header.jwt` with protected header:
  `{ "alg": "HS256", "crit": ["cnf"], "cnf": {"jkt": "thumb-42"} }`

### Reproduction
Run the cross‑runtime demo:
```bash
make  demo
```

Expected output for each token (strict verifiers reject; Authlib accepts):

For `tokens/unknown_crit.jwt`:
```
Strict(Nimbus): REJECTED (unknown critical header: bork)
Strict(Node jose): REJECTED (unrecognized crit)
Lenient(Authlib): ACCEPTED -> payload={'sub': '123', 'role': 'user'}
```

For `tokens/cnf_header.jwt`:
```
Strict(Nimbus): REJECTED (unknown critical header: cnf)
Strict(Node jose): REJECTED (unrecognized crit)
Lenient(Authlib): ACCEPTED -> payload={'sub': '123', 'role': 'user'}
```

Environment notes:
- Authlib version used: `1.6.3` (from PyPI)
- Node `jose` version: `^5`
- Nimbus JOSE+JWT versi