chore(deps): update dependency pyjwt to v2.13.0 [security] - #1404
Open
renovate[bot] wants to merge 1 commit into
Open
chore(deps): update dependency pyjwt to v2.13.0 [security]#1404renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
renovate
Bot
force-pushed
the
renovate/pypi-pyjwt-vulnerability
branch
2 times, most recently
from
March 13, 2026 14:52
6981413 to
62046e3
Compare
renovate
Bot
force-pushed
the
renovate/pypi-pyjwt-vulnerability
branch
2 times, most recently
from
March 30, 2026 21:42
62046e3 to
ff2852c
Compare
renovate
Bot
force-pushed
the
renovate/pypi-pyjwt-vulnerability
branch
2 times, most recently
from
April 27, 2026 21:53
ff2852c to
f15806c
Compare
renovate
Bot
force-pushed
the
renovate/pypi-pyjwt-vulnerability
branch
from
August 26, 2026 20:58
f15806c to
e3a86dc
Compare
renovate
Bot
force-pushed
the
renovate/pypi-pyjwt-vulnerability
branch
from
September 2, 2026 20:40
e3a86dc to
b9122d8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
==2.1.0→==2.13.0Key confusion through non-blocklisted public key formats
CVE-2022-29217 / GHSA-ffqj-6fqr-9h24
More information
Details
Impact
What kind of vulnerability is it? Who is impacted?
Disclosed by Aapo Oksman (Senior Security Specialist, Nixu Corporation).
Patches
Users should upgrade to v2.4.0.
Workarounds
Always be explicit with the algorithms that are accepted and expected when decoding.
References
Are there any links users can visit to find out more?
For more information
If you have any questions or comments about this advisory:
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
PyJWT accepts unknown
critheader extensionsCVE-2026-32597 / GHSA-752w-5fwx-jx9f
More information
Details
Summary
PyJWT does not validate the
crit(Critical) Header Parameter defined inRFC 7515 §4.1.11. When a JWS token contains a
critarray listingextensions that PyJWT does not understand, the library accepts the token
instead of rejecting it. This violates the MUST requirement in the RFC.
This is the same class of vulnerability as CVE-2025-59420 (Authlib),
which received CVSS 7.5 (HIGH).
RFC Requirement
RFC 7515 §4.1.11:
Proof of Concept
Expected:
jwt.exceptions.InvalidTokenError: Unsupported critical extension: x-custom-policyActual: Token accepted, payload returned.
Comparison with RFC-compliant library
Impact
gateway using jwcrypto rejects, backend using PyJWT accepts)
critcarries enforcement semantics(MFA, token binding, scope restrictions)
cnf(Proof-of-Possession) can besilently ignored
Suggested Fix
In
jwt/api_jwt.py, add validation in_validate_headers()ordecode():CWE
References
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
PyJWT: Public-key JWK accepted as HMAC secret enables forged HS256 tokens when mixed families are allowed
CVE-2026-48526 / GHSA-xgmm-8j9v-c9wx
More information
Details
Summary
When the verifier is decoding JSON Web Tokens, while supporting both asymmetric and HMAC algorithms, the library does not validate use of JSON Web Keys in HMAC algorithm, allowing attacker to use the issuer public key as the secret key for HMAC algorithm.
Details
In JWT algorithm confusion attack, the verifier is mistakenly use of public key to be used as the shared secret in symmetric algorithms.
In pyjwt case, when the verifier is supporting both HMAC with other asymmetric algorithm and mistakenly using the public key of the issuer to verify the token as demonstrated in the following example:
jws.decode(token, key=rsa_jwk_json, algorithms=["HS256","RS256"]))An attacker who specifies in the token header to use HMAC, will cause the verifier to accept the JWK as the secret key in HMAC algorithm.
The attacker will be able to forge JWT signed with the public key of the issuer to impersonate any user.
If we look on current protections implemented in the library, at class HMACAlgorithm:
We can observe that there is a protection against this type of attacks but only when the verifier is using PEM format or SSH key to verify the token. JSON Web Keys, on the other hand will pass the validation.
In The following example:
jws.decode(token, key=rsa_jwk_json, algorithms=["HS256","RS256"]))There is indeed a wrong implementation of the verifier, but a stronger protection in the library side will prevent and protect against those type of misconfiugrations.
The bypass happens only if the verifier:
(a) allows HS* and an asymmetric algorithm in the same call and (b) passes a public-key value as key.
PoC
Please run the code and observe the payload printed in clear text({"sub":"alice","admin":true}')
Impact
Unauthenticated token forgery → full identity/role impersonation at the resource server (authorization bypass).
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)
CVE-2026-48524 / GHSA-fhv5-28vv-h8m8
More information
Details
Summary
PyJWKClient.get_signing_key() forces a fresh HTTP request to the JWKS endpoint for every JWT with an unknown kid value, with no rate limiting. Since kid comes from the unverified token header, an attacker can trigger unlimited outbound requests.
Additionally, fetch_data() finally block clears the JWKS cache on network error.
Root Cause
jwt/jwks_client.py:172-198 - get_signing_key(kid) calls get_signing_keys(refresh=True) for unknown kids, bypassing TTL cache with no cooldown.
jwt/jwks_client.py:120-122 - finally block writes None to cache on error, clearing valid data.
Impact
Suggested Fix
Affected Versions
All versions with PyJWKClient (2.4.0 through 2.12.1)
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:LReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
PyJWKClient: missing scheme allowlist enables CVE-2024-21643-class SSRF + token forgery via file://, ftp://, data: schemes
CVE-2026-48522 / GHSA-993g-76c3-p5m4
More information
Details
Summary
PyJWKClient passes its
uriargument directly tourllib.request.urlopen()which uses Python stdlib's defaultOpenerDirectorregisteringHTTPHandler,HTTPSHandler,FTPHandler,FileHandler, andDataHandler. There is currently no documented option to restrict which schemes PyJWKClient will fetch.If an application's
jkuURL ingestion path accepts attacker-influenced URLs (e.g., from JWT header, configuration file, OAuth flow parameter), the attacker can:file://(SSRF on local filesystem) — the file's contents are passed tojson.load.jwt.decode()accepts.Affected versions
Tested and reproducible on PyJWT 2.11.0 and 2.12.1. Likely all versions back to PyJWKClient introduction.
Reproducer (full attack chain — verified empirically)
Cross-library evidence — PyJWT is the outlier
The same composition pattern is structurally safe in 4 other mainstream JWT libraries:
jku=file://...fetch()rejects non-http(s) at fetch-spec layerhttp.DefaultTransportonly registers http/httpsHttpDocumentRetrieverdefaultsRequireHttps=truePyJWT is the only library of these 5 where the default behavior allows
file://to reach the fetch layer.Recommended fix
Add
allowed_schemes: tuple[str, ...] = ("https", "http")kwarg toPyJWKClient.__init__. Pre-validate URL scheme before invokingurllib.request.urlopen. URLs with disallowed schemes raisePyJWKClientErrorbefore any fetch is attempted.Diff sketch against
jwt/jwks_client.pyTests to add
Compatibility
allowed_schemes=("https", "http")preserves backwards compatibility for the overwhelming majority of callers using HTTP/HTTPS JWKS endpointsClass precedent
This is the same class as CVE-2024-21643 (Apache Jena JKU-trust: attacker-supplied JKU URL fetched without scheme validation). NVD-rated CVSS 7.5.
Prior art (verified 2026-05-06)
Confirmed via live recon (NVD direct, OSV.dev, PyJWT GitHub Security Advisories, issue/PR keyword search, CHANGELOG inspection):
Credit
Reported by Keijo Tuominen — independent security research at CMHT.tech (https://cmht.tech).
Reproduction artifacts available on request: full multi-language probe pack (5 wrappers × 25 fixtures × 125 cells) demonstrating cross-library divergence at the URL-scheme boundary.
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
jpadilla/pyjwt (pyjwt)
v2.13.0Compare Source
v2.12.1Compare Source
Changed
Remove algorithm requirement from JWT API, instead relying on JWS API for enforcement, by @luhn in
#​975 <https://github.com/jpadilla/pyjwt/pull/975>__Use
Sequencefor parameter types rather thanListwhere applicable by @imnotjames in#​970 <https://github.com/jpadilla/pyjwt/pull/970>__Add JWK support to JWT encode by @luhn in
#​979 <https://github.com/jpadilla/pyjwt/pull/979>__Encoding and decoding payloads using the
nonealgorithm by @jpadilla in#c2629f6 <https://github.com/jpadilla/pyjwt/commit/c2629f66c593459e02616048443231ccbe18be16>__Before:
.. code-block:: pycon
After:
.. code-block:: pycon
Added validation for 'sub' (subject) and 'jti' (JWT ID) claims in tokens by @Divan009 in
#​1005 <https://github.com/jpadilla/pyjwt/pull/1005>__Refactor project configuration files from
setup.cfgtopyproject.tomlby @cleder in#​995 <https://github.com/jpadilla/pyjwt/pull/995>__Ruff linter and formatter changes by @gagandeepp in
#​1001 <https://github.com/jpadilla/pyjwt/pull/1001>__Drop support for Python 3.8 (EOL) by @kkirsche in
#​1007 <https://github.com/jpadilla/pyjwt/pull/1007>__Fixed
#​972 <https://github.com/jpadilla/pyjwt/pull/972>__#​973 <https://github.com/jpadilla/pyjwt/pull/973>__#​992 <https://github.com/jpadilla/pyjwt/pull/992>__#​980 <https://github.com/jpadilla/pyjwt/pull/980>__#​993 <https://github.com/jpadilla/pyjwt/pull/993>__pyproject.tomlinpre-commitby @cleder in#​1002 <https://github.com/jpadilla/pyjwt/pull/1002>__#​1003 <https://github.com/jpadilla/pyjwt/pull/1003>__v2.12.0Compare Source
Security
What's Changed
New Contributors
Full Changelog: jpadilla/pyjwt@2.11.0...2.12.0
v2.11.0Compare Source
Fixed
v2.10.1Compare Source
Fixed
issclaim. Thanks @fabianbadoi! (See: GHSA-75c5-xw7c-p5pm)Full Changelog: jpadilla/pyjwt@2.10.0...2.10.1
v2.10.0Compare Source
What's Changed
iatexception docs by @pachewise in #974subandjticlaims for the token by @Divan009 in #1005New Contributors
Full Changelog: jpadilla/pyjwt@2.9.0...2.10.0
v2.9.0Compare Source
What's Changed
New Contributors
Full Changelog: jpadilla/pyjwt@2.8.0...2.9.0
v2.8.0Compare Source
What's Changed
strict_audoption by @woodruffw in #902New Contributors
Configuration
📅 Schedule: (in timezone UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.