Disclosure summary
## Summary PyJWT 2.13.0 accepts compact JWS signature segments containing characters that are not in the Base64URL alphabet. Appending `!!!!` to a valid signature does not change the decoded signature bytes or authenticated claims, but it changes the serialized token and its SHA-256 hash. An application that indexes logout or revocation state by the raw token therefore rejects the logged-out token and accepts its no-key alternate serialization. This report separates two issues: permissive compact-JWS decoding is the library behavior, while using raw serialized JWT text as a security identity is a dangerous application composition. A `jti`-indexed control blocks both representations. ## Affected Version Confirmed with PyJWT 2.13.0 on CPython 3.13. The mutation changes only the signature segment and requires no signing key. ## End-to-End Reproduction ```bash .venv-research/bin/python 06-practical-testing/revocation-bypass-lab.py ``` The loopback-only lab performs: 1. Issue a valid HS256 admin token. 2. Access `/protected` successfully. 3. Log out the canonical token and store `SHA256(raw_token)`. 4. Confirm canonical replay returns HTTP 401. 5. Append `!!!!` to only the signature seg
Source-specific records & product guidance
Sources retain their own attribution and scoring. Follow the original record to confirm affected versions, fixed releases, and configuration conditions.
GitHub Reviewed Security Advisories · GHSA-hxm8-2xgr-2p9m
Open original source · Updated Sep 29, 2026
PyJWT: Non-canonical signature segments enable raw-token revocation bypass
Source severity: MEDIUM / 0
| Ecosystem | Package | Affected range | First patched |
|---|---|---|---|
| pip | PyJWT | 2.14.0 |
Original records & references
- NIST NVD record
- CVE Program record
- github.com — Reviewed advisory
PUBLISHED 2026-09-29T19:17:55-04:00
MODIFIED 2026-09-29T19:17:56-04:00
INGESTED 2026-10-06T11:43:08-04:00