# What changed in pyjwt

> 35 changes in pyjwt 2 from its official release notes, upgrade guides and advisories: 7 breaking, 17 security, 1 new APIs and options. Each one cited. Sources checked 2026-10-21. HTML: https://unstale.sh/pypi/pyjwt/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## pyjwt 2

### Breaking changes

- The encoder adds b64 to crit, and the decoder rejects b64=false tokens that omit it. (2.13.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.13.0)
- Requires the compact-form payload segment to be empty for detached-payload JWS and no longer decodes that unused segment. (2.13.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.13.0), [security advisory](https://github.com/advisories/GHSA-W7VC-732C-9M39)
- Rejects JWK-shaped JSON strings as HMAC keys, preventing algorithm confusion when symmetric and asymmetric algorithms are both allowed. (2.13.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.13.0), [security advisory](https://github.com/advisories/GHSA-XGMM-8J9V-C9WX)
- Empty HMAC keys now raise InvalidKeyError instead of being accepted with a warning. (2.13.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.13.0)
- Verification now requires the token header alg to match the algorithm bound to the PyJWK. (2.13.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.13.0), [security advisory](https://github.com/advisories/GHSA-JQ35-7PRP-9V3F)
- Rejects URIs whose scheme is not http or https, preventing access through unintended schemes. (2.13.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.13.0), [security advisory](https://github.com/advisories/GHSA-993G-76C3-P5M4)
- The RFC 7515 crit header parameter is validated, affecting how tokens with critical header parameters are handled. (2.12.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.12.0), [security advisory](https://github.com/advisories/GHSA-752W-5FWX-JX9F)

### Security

- PyJWT accepts inconsistent OKP x/d JWKs, causing public/private key identity confusion (2.15.0) — [security advisory](https://github.com/advisories/GHSA-X33G-CR3X-6449)
- PyJWT: Unauthenticated RecursionError DoS in pre-verification payload parse (PyJWKClient.get_signing_key_from_jwt / verify_signature=False) (2.15.0) — [security advisory](https://github.com/advisories/GHSA-42VR-XJ54-VC7V)
- PyJWT accepts public JWK containers as HMAC secrets (2.14.0) — [security advisory](https://github.com/advisories/GHSA-W2CX-738M-MC7W)
- PyJWT: Asymmetric-PEM detection bypass: whitespace/line-ending-mutated public keys skip the HS/asymmetric confusion guard (2.14.0) — [security advisory](https://github.com/advisories/GHSA-FFC3-869F-JXW9)
- PyJWT BOM Bypass (2.14.0) — [security advisory](https://github.com/advisories/GHSA-R6X4-923Q-G947)
- PyJWT: Malformed RSA JWK aborts parsing of an entire JWK Set (2.14.0) — [security advisory](https://github.com/advisories/GHSA-W6J9-CWV2-H6WQ)
- PyJWT: Non-canonical signature segments enable raw-token revocation bypass (2.14.0) — [security advisory](https://github.com/advisories/GHSA-HXM8-2XGR-2P9M)
- PyJWT: Public keys in DER form are accepted as HMAC secrets, bypassing the CVE-2022-29217 guard (2.14.0) — [security advisory](https://github.com/advisories/GHSA-P4G4-X82P-Q773)
- PyJWT: PyJWK accepts empty HMAC keys, bypassing PyJWT's empty-key validation (2.14.0) — [security advisory](https://github.com/advisories/GHSA-9J54-FG26-WV3R)
- PyJWT: PyJWKClient follows redirects when fetching JWKS (2.14.0) — [security advisory](https://github.com/advisories/GHSA-9V7F-9G4P-FFGJ)
- PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524) (2.14.0) — [security advisory](https://github.com/advisories/GHSA-2GX3-RCP4-G85Q)
- PyJWT: ReDoS vulnerability when calling the `is_pem_format` function. (2.14.0) — [security advisory](https://github.com/advisories/GHSA-JWRC-G2Q2-PQ5P)
- PyJWT: Uncaught RecursionError in jwt.decode() on deeply nested token header (2.14.0) — [security advisory](https://github.com/advisories/GHSA-8WJV-2P76-3863)
- A failed fetch no longer evicts valid cached JWK sets, so transient endpoint errors do not cause application-wide authentication failure. (2.13.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.13.0), [security advisory](https://github.com/advisories/GHSA-FHV5-28VV-H8M8)
- Per-call options are forwarded to signature verification, so enforce_minimum_key_length now takes effect when passed to decode. (2.13.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.13.0)
- Keys are validated against the allowed types for their algorithm family. (2.11.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.11.0)
- Issuer claim type checks are added. (2.11.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.11.0)

### New APIs and options

- PyJWKSet gains an iterator, allowing developers to iterate over its keys. (2.11.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.11.0)

### Behavior and default changes

- Encoding without an explicit algorithm now uses the PyJWK algorithm. (2.12.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.12.0)
- Passing algorithm=None is mapped to the "none" algorithm. (2.11.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.11.0)

### Tooling

- The PyJWKSet.keys annotation was updated for pyright. (2.12.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.12.0)

### Fixes and other changes

- Adds typing_extensions as a dependency for Python versions below 3.11. (2.12.1) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.12.1)
- HTTPError is closed to prevent a ResourceWarning on Python 3.14. (2.12.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.12.0)
- PyJWK no longer stores a reference to the algorithms dict. (2.12.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.12.0)
- The options parameter's typing and logic are improved in decode and decode_complete. (2.11.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.11.0)
- The lifespan and timeout type annotations use float instead of int. (2.11.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.11.0)
- The method's type annotation is corrected. (2.11.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.11.0)
- PyJWT adds support for Python 3.14. (2.11.0) — [release notes](https://github.com/jpadilla/pyjwt/releases/tag/2.11.0)
