build(deps): bump the uv group across 8 directories with 2 updates
Bumps the uv group with 2 updates in the /examples/voice-agents/candidate-screening directory: pyjwt and urllib3.
Bumps the uv group with 2 updates in the /examples/voice-agents/insurance-adjuster directory: pyjwt and urllib3.
Bumps the uv group with 2 updates in the /examples/voice-agents/mortgage-lending directory: pyjwt and urllib3.
Bumps the uv group with 2 updates in the /moss-live-labs/examples/advanced-voice-agent directory: pyjwt and urllib3.
Bumps the uv group with 2 updates in the /moss-live-labs/examples/voice-agent directory: pyjwt and urllib3.
Bumps the uv group with 1 update in the /packages/agora-moss directory: pyjwt.
Bumps the uv group with 2 updates in the /packages/moss-data-connector/moss-connector-supabase directory: pyjwt and urllib3.
Bumps the uv group with 1 update in the /packages/pipecat-moss directory: urllib3.
Updates pyjwt from 2.12.1 to 2.15.0
Release notes
Sourced from pyjwt's releases.
2.15.0
See the 2.15.0 changelog for complete release details.
2.14.0
See the 2.14.0 changelog for the complete release details and related security advisories.
2.13.0
PyJWT 2.13.0 — Security Release
This release bundles five security fixes plus three additional hardening / spec-compliance changes. We recommend all users upgrade.
Security
GHSA-xgmm-8j9v-c9wx— JWK JSON accepted as HMAC secret (algorithm confusion).HMACAlgorithm.prepare_keypreviously rejected PEM- and SSH-formatted asymmetric keys but did not catch a JWK passed as a raw JSON string. In a verifier configured with both symmetric and asymmetric algorithms inalgorithms=[…]and a raw-JSON JWK as the key, an attacker could forge HS256 tokens using the JWK text as the HMAC secret. The guard has been extended to reject any JWK-shaped JSON. Reported by@aradona91.
GHSA-jq35-7prp-9v3f— Algorithm allow-list bypass withPyJWK/PyJWKClient. When verifying with aPyJWK, the caller'salgorithms=[…]allow-list was checked against the token headeralgas a string only; actual verification used the algorithm bound to thePyJWK. An attacker who controlled a registered JWKS key could sign with one algorithm and advertise another on the header. PyJWT now requires the token headeralgto match thePyJWK's algorithm before verification. Reported by@sushi-gif.
GHSA-w7vc-732c-9m39— DoS via base64 decode of unused payload segment whenb64=false. For detached-payload JWS (b64=false), the compact-form payload segment was base64-decoded before being discarded in favor of the caller-supplieddetached_payload. An attacker could inflate the unused segment to force CPU + memory cost without holding a valid signature. The segment is now required to be empty per RFC 7515 Appendix F, and is no longer decoded. Reported by@thesmartshadow.
GHSA-993g-76c3-p5m4—PyJWKClientaccepts non-HTTP(S) URIs.PyJWKClient.fetch_datapassed its URI tourllib.request.urlopen, which by default also handlesfile://,ftp://, anddata:schemes. An application that fed an attacker-influenced URI intoPyJWKClientcould be coerced into reading local files or reaching other unintended schemes.PyJWKClientnow rejects any URI whose scheme isn'thttporhttps. Reported by@KEIJOT.
GHSA-fhv5-28vv-h8m8—PyJWKClientcache wiped on fetch error. Afinally-blockput(jwk_set=None)cleared the JWK Set cache whenever a fetch raised, turning a transient JWKS-endpoint outage into application-wide auth failure. The cache write was moved into the success path; transient errors no longer evict valid cached keys. Reported by@eddieran.Fixed
- Reject empty HMAC keys outright in
HMACAlgorithm.prepare_keywithInvalidKeyErrorinstead of accepting them with only a warning. Defends against theos.getenv("JWT_SECRET", "")footgun. Thanks to@SnailSploitand@spartan8806for the reports.- Forward per-call
options(includingenforce_minimum_key_length) fromPyJWT.decodethrough toPyJWS._verify_signature. The option was previously silently dropped between the two layers, so it only took effect when set on thePyJWTinstance. Thanks to@WLUBfor the report.- RFC 7797 §3 compliance for
b64=false: the encoder now auto-adds"b64"tocrit, and the decoder rejects tokens that setb64=falsewithout listing it incrit. Thanks to@MachineLearning-Nerdfor the report.Changed
- Migrate the
dev,docs, andtestspackage extras to dependency groups, by@kurtmckeein #1152.Upgrade notes
Most fixes are invisible to correctly-configured callers. A few behavioral changes you may encounter:
- Empty HMAC keys now raise. If your app passed
""orb""as a secret (often via a missing env var, e.g.os.getenv("JWT_SECRET", "")),encode/decodewill now raiseInvalidKeyError. This is the intended behavior — fix the configuration.PyJWKdecoding now requires the token'salgto match the JWK's algorithm. Previously a mismatch was silently honored if the headeralgappeared in the allow-list. Tokens that relied on this mismatch will now fail withInvalidAlgorithmError.PyJWKClientnow rejects non-HTTP(S) URIs at construction time. Tests or dev environments that fetched JWKS fromfile://URIs need to switch to a local HTTP server or load the JWKS by other means (e.g. constructPyJWKSet.from_dict(...)directly).b64=falsetokens are now strictly RFC 7515 / 7797 compliant. Tokens with a non-empty compact-form payload segment, or that omit"b64"fromcrit, will be rejected. PyJWT-produced tokens always satisfy both invariants, so round-trips through PyJWT are unaffected.enforce_minimum_key_lengthset per-call now takes effect. Callers who passedoptions={"enforce_minimum_key_length": True}tojwt.decode()previously got no enforcement; they will now getInvalidKeyErroron undersized keys, as documented.Full changelog: https://github.com/jpadilla/pyjwt/compare/2.12.1...2.13.0
Changelog
Sourced from pyjwt's changelog.
v2.15.0 <https://github.com/jpadilla/pyjwt/compare/2.14.0...2.15.0>__Security
- Wrap recursion errors from deeply nested JWT payloads in ``DecodeError`` instead of exposing a raw ``RecursionError``.Added
- Support Python 3.15 by @kytta in `[#1202](https://github.com/jpadilla/pyjwt/issues/1202) <https://github.com/jpadilla/pyjwt/pull/1202>`__
Changed
JWKSetCachenow stores the parsedPyJWKSetrather than the raw JWKS payload, so a cache hit no longer re-parses every key.JWKSetCache.put()accepts either form and raisesPyJWKSetErrorfor anything else. As a result,PyJWKClient.get_jwk_set()returns the samePyJWKSetinstance for as long as it stays cached, rather than a freshly built one per call in[#1208](https://github.com/jpadilla/pyjwt/issues/1208) <https://github.com/jpadilla/pyjwt/pull/1208>__PyJWKClient.fetch_data()now raisesPyJWKClientError("The JWKS endpoint did not return a JSON object")when the endpoint response is not a JSON object, instead of returning it forget_jwk_set()to reject. Callers reaching the JWKS throughget_jwk_set()see the same error as before in[#1208](https://github.com/jpadilla/pyjwt/issues/1208) <https://github.com/jpadilla/pyjwt/pull/1208>__Fixed
- Return cached ``PyJWKSet`` values from ``PyJWKClient.get_jwk_set()`` instead of raising ``PyJWKClientError("The JWKS endpoint did not return a JSON object")``. ``JWKSetCache.put()`` documents ``PyJWKSet`` as the cached value, so callers pre-populating the cache to avoid a network round-trip could not read it back in `[#914](https://github.com/jpadilla/pyjwt/issues/914) <https://github.com/jpadilla/pyjwt/issues/914>`__ and `[#1208](https://github.com/jpadilla/pyjwt/issues/1208) <https://github.com/jpadilla/pyjwt/pull/1208>`__ - ``PyJWKClient.get_jwk_set()`` now caches the key set it returns, so a ``fetch_data()`` override that filters or transforms the JWKS is no longer undone by the next cache hit in `[#1208](https://github.com/jpadilla/pyjwt/issues/1208) <https://github.com/jpadilla/pyjwt/pull/1208>`__ - Raise the documented ``PyJWTError`` subclass instead of leaking a ``TypeError`` when the ``exp``, ``nbf``, or ``iat`` claim decodes to a non-numeric, non-string value such as a list, dict, or ``null``. - Reject OKP JWK private keys when their public ``x`` component does not match the private ``d`` component. - Treat malformed JWK Set members as unusable keys rather than letting ``AttributeError`` or ``TypeError`` escape ``PyJWKSet``. A member that is not </tr></table> </code></pre> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary><ul>
<li><a href="https://github.com/jpadilla/pyjwt/commit/1d41a6478e1562e68ff667fcd703356acf085f68"><code>1d41a64</code></a> chore: prepare 2.15.0 release</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/9bc06658f875b9b40091539140bbbdc4639161c3"><code>9bc0665</code></a> fix: make recursive payload tests deterministic</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/5fde08a6cf906aa7698de2d6391d88b73006b17b"><code>5fde08a</code></a> fix: normalize recursive JWT payload errors</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/171062d2d734315272a901100aa4b109f2fc3c19"><code>171062d</code></a> utils: mention bytes in force_bytes type error (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1173">#1173</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/c9d4d5375bf464ef363506fed9eb6e7f33217ab6"><code>c9d4d53</code></a> docs/conf: drop duplicate 'and' from read() docstring (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1174">#1174</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/2763752196113e1473b0ed7905aa6034aedfbe53"><code>2763752</code></a> Add support for Python 3.15 (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1202">#1202</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/4adcd02722f5011c60079d3978dfc167b9a8eaa5"><code>4adcd02</code></a> Catch http.client.HTTPException in PyJWKClient.fetch_data (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1201">#1201</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/9e501d993b4d3e7dba14bdb1722b1d993ac75097"><code>9e501d9</code></a> fix: correct docstring typo in _validate_jti (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1179">#1179</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/4047c44d51950ffda15f40054508d3f17c43b1e2"><code>4047c44</code></a> docs: clarify JWK certificate member handling (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1212">#1212</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/f4e2b59f543cc82d46d9d69922bba59e804216b9"><code>f4e2b59</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1210">#1210</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/jpadilla/pyjwt/compare/2.12.1...2.15.0">compare view</a></li>
</ul>
</details>
<br />Updates
urllib3from 2.7.0 to 2.8.0Release notes
Sourced from urllib3's releases.
2.8.0
🚀 urllib3 is fundraising for HTTP/2 support
urllib3 is raising ~$40,000 USD to release HTTP/2 support and ensure long-term sustainable maintenance of the project. If your company or organization uses Python and would benefit from HTTP/2 support in Requests, pip, cloud SDKs, and thousands of other projects please consider contributing financially to ensure HTTP/2 support is developed sustainably and maintained for the long-haul.
Thank you for your support.
Security
Fixed the following security issues:
- The TLS configuration for HTTPS proxies could be ignored or overridden. (High severity, GHSA-8988-9cw3-xx77)
HTTPResponse.stream()andread_chunked()could buffer a chunk-size line of unbounded length in memory. (High severity, GHSA-vxq7-64xx-v4gw)- Chunked Deflate streaming could enter an infinite loop. (Medium severity, GHSA-gh4c-6fx4-qh6g)
[!IMPORTANT] urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or overridden by destination settings. Configurations relying on that behavior may require changes.
Configure proxy CA certificates and client certificates in
proxy_ssl_context, and proxy identity checks withproxy_assert_hostnameorproxy_assert_fingerprint. Destination client certificates and identity overrides no longer apply to HTTPS forwarding proxy connections.[!NOTE] CVE IDs had not yet been assigned to these advisories at the time of release due to a backlog at GitHub's CNA.
Deprecations & Removals
- Deprecated using an empty collection as the
Retryoptionallowed_methodsto retry any verb. (#5044)Features
- Added
Url.auth_decodedandUrl.auth_decoded_joinedconvenience properties to the result ofparse_url(). (#4945)- Added
basic_auth_encodingandproxy_basic_auth_encodingparameters tourllib3.util.make_headers(). (#5092)Bugfixes
Fixed response header handling to replace obsolete folded header lines (
obs-fold) with spaces in accordance with RFC 9112, preventing raw CRLF sequences from appearing in header values such asSet-Cookie. (#1362)Fixed usage of
proxy_ssl_contextwithProxyManagerwhenuse_forwarding_for_https=True. Passingssl_contextinstead ofproxy_ssl_contextfor HTTPS proxies in this configuration now emits aFutureWarningand will raise an error in v3.0. (#2577)Changed behavior of the default
ConnectionPool.poolinitialization.LifoQueueis now resolved from thequeuemodule after theConnectionPoolis instantiated instead of using the default cachedQueueClsclass property. This is done because sometimes thequeue.LifoQueueis monkey-patched late in the program, such as by gevent. (#3289)Raised
UnrewindableBodyErrorinstead ofValueErrorwhen retrying a request whose body hadtell()but notseek(). (#3779)Decoded percent-encoded SOCKS proxy credentials before authenticating with the proxy server. (#3785)
Fixed
HTTPResponse.drain_conn()to discard unread response data in 64 KiB chunks (same as the defaultamtwhen doingHTTPResponse.stream(...)). (#5019)Fixed
is_ipaddress()to detect non-standard IPv4 forms accepted bysocket.connect, such as hex (0x7f000001), octal (0177.0.0.1), and decimal integers (2130706433), ensuring SSL certificate verification uses the correct mode for these addresses. (#5029)Fixed
HTTPConnectionPool.urlopenraising a misleadingFullPoolErrorinstead ofValueErrorwhen called with an invalidtimeoutargument on a pool created withblock=True. (#5059)Fixed port-zero handling to preserve explicit
:0values instead of substituting the default ports 80 or 443 in URL parsing, pool selection, proxy configuration,connection_from_url(), and HTTP/2 request authority. (#5071, #5101)Fixed a bug where
PoolManagerpassed theassert_hostnameandassert_fingerprintparameters to HTTP connection pools. (#5077)Fixed
HTTPConnectionPool.urlopen()and HTTP proxy forwarding to strip URL fragments from absolute request targets before sending requests. (#5079)Added safeguards to the proxy tunneling code to prevent potential security issues when handling invalid characters in the proxy host and HTTP headers. This change affects users of Python 3.10, Python 3.11, and Python 3.12 when the standard library does not contain the fix; those on newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the same security fixes. (#5091)
Fixed
HTTPSConnection.connect()overridingProxyConfig.ssl_context's certificate policy and proxy identity checks with the target connection's TLS settings when forwarding through an HTTPS proxy.
HTTPSConnectionno longer applies target SNI, assertions, or client credentials to forwarding proxy handshakes and continues to use itsssl_contextas a fallback when an HTTPS proxy forwards an HTTP target. (#5093)Fixed URL parsing to more strictly enforce RFC 3986 host syntax, rejecting invalid host input such as raw spaces and control characters, malformed percent-encodings, and percent-encoded control characters in HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel targets. Host normalization now also follows RFC 3986 normalization rules for percent-encoded octets by decoding percent-encoded unreserved characters and uppercasing the hexadecimal digits of retained percent-encoded octets. (#5095)
... (truncated)
Changelog
Sourced from urllib3's changelog.
2.8.0 (2026-09-15)
Security
Fixed the following security issues:
- The TLS configuration for HTTPS proxies could be ignored or overridden. (High severity,
GHSA-8988-9cw3-xx77 <https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77>__)HTTPResponse.stream()andread_chunked()could buffer a chunk-size line of unbounded length in memory. (High severity,GHSA-vxq7-64xx-v4gw <https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw>__)- Chunked Deflate streaming could enter an infinite loop. (Medium severity,
GHSA-gh4c-6fx4-qh6g <https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g>__).. caution::
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or overridden by destination settings. Configurations relying on that behavior may require changes.
Configure proxy CA certificates and client certificates inproxy_ssl_context, and proxy identity checks withproxy_assert_hostnameorproxy_assert_fingerprint. Destination client certificates and identity overrides no longer apply to HTTPS forwarding proxy connections.Deprecations & Removals
- Deprecated using an empty collection as the
Retryoptionallowed_methodsto retry any verb. ([#5044](https://github.com/urllib3/urllib3/issues/5044) <https://github.com/urllib3/urllib3/issues/5044>__)Features
- Added
Url.auth_decodedandUrl.auth_decoded_joinedconvenience properties to the result ofparse_url(). ([#4945](https://github.com/urllib3/urllib3/issues/4945) <https://github.com/urllib3/urllib3/issues/4945>__)- Added
basic_auth_encodingandproxy_basic_auth_encodingparameters tourllib3.util.make_headers(). ([#5092](https://github.com/urllib3/urllib3/issues/5092) <https://github.com/urllib3/urllib3/issues/5092>__)Bugfixes
... (truncated)
Commits
b1d30abRelease 2.8.09016d7eSkiptest_read_chunked_with_trailing_data_does_not_hangfor brotlicffi (#5258)9101f58Fixnox -s docswarning (#5256)cd770b0Merge commit from forkea2ad7bMerge commit from fork0716e31Fix loading unencrypted client keys with a password in pyOpenSSL (#5255)43c68c8Test pickling ofInvalidChunkLength(#5247)308b279Share security policy between GitHub and Read the Docs (#5253)53fa073Add policy on duplicate pull requests (#5252)5f2a6a8Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (#5232)- Additional commits viewable in compare view
Updates
pyjwtfrom 2.13.0 to 2.15.0Release notes
Sourced from pyjwt's releases.
2.15.0
See the 2.15.0 changelog for complete release details.
2.14.0
See the 2.14.0 changelog for the complete release details and related security advisories.
2.13.0
PyJWT 2.13.0 — Security Release
This release bundles five security fixes plus three additional hardening / spec-compliance changes. We recommend all users upgrade.
Security
GHSA-xgmm-8j9v-c9wx— JWK JSON accepted as HMAC secret (algorithm confusion).HMACAlgorithm.prepare_keypreviously rejected PEM- and SSH-formatted asymmetric keys but did not catch a JWK passed as a raw JSON string. In a verifier configured with both symmetric and asymmetric algorithms inalgorithms=[…]and a raw-JSON JWK as the key, an attacker could forge HS256 tokens using the JWK text as the HMAC secret. The guard has been extended to reject any JWK-shaped JSON. Reported by@aradona91.
GHSA-jq35-7prp-9v3f— Algorithm allow-list bypass withPyJWK/PyJWKClient. When verifying with aPyJWK, the caller'salgorithms=[…]allow-list was checked against the token headeralgas a string only; actual verification used the algorithm bound to thePyJWK. An attacker who controlled a registered JWKS key could sign with one algorithm and advertise another on the header. PyJWT now requires the token headeralgto match thePyJWK's algorithm before verification. Reported by@sushi-gif.
GHSA-w7vc-732c-9m39— DoS via base64 decode of unused payload segment whenb64=false. For detached-payload JWS (b64=false), the compact-form payload segment was base64-decoded before being discarded in favor of the caller-supplieddetached_payload. An attacker could inflate the unused segment to force CPU + memory cost without holding a valid signature. The segment is now required to be empty per RFC 7515 Appendix F, and is no longer decoded. Reported by@thesmartshadow.
GHSA-993g-76c3-p5m4—PyJWKClientaccepts non-HTTP(S) URIs.PyJWKClient.fetch_datapassed its URI tourllib.request.urlopen, which by default also handlesfile://,ftp://, anddata:schemes. An application that fed an attacker-influenced URI intoPyJWKClientcould be coerced into reading local files or reaching other unintended schemes.PyJWKClientnow rejects any URI whose scheme isn'thttporhttps. Reported by@KEIJOT.
GHSA-fhv5-28vv-h8m8—PyJWKClientcache wiped on fetch error. Afinally-blockput(jwk_set=None)cleared the JWK Set cache whenever a fetch raised, turning a transient JWKS-endpoint outage into application-wide auth failure. The cache write was moved into the success path; transient errors no longer evict valid cached keys. Reported by@eddieran.Fixed
- Reject empty HMAC keys outright in
HMACAlgorithm.prepare_keywithInvalidKeyErrorinstead of accepting them with only a warning. Defends against theos.getenv("JWT_SECRET", "")footgun. Thanks to@SnailSploitand@spartan8806for the reports.- Forward per-call
options(includingenforce_minimum_key_length) fromPyJWT.decodethrough toPyJWS._verify_signature. The option was previously silently dropped between the two layers, so it only took effect when set on thePyJWTinstance. Thanks to@WLUBfor the report.- RFC 7797 §3 compliance for
b64=false: the encoder now auto-adds"b64"tocrit, and the decoder rejects tokens that setb64=falsewithout listing it incrit. Thanks to@MachineLearning-Nerdfor the report.Changed
- Migrate the
dev,docs, andtestspackage extras to dependency groups, by@kurtmckeein #1152.Upgrade notes
Most fixes are invisible to correctly-configured callers. A few behavioral changes you may encounter:
- Empty HMAC keys now raise. If your app passed
""orb""as a secret (often via a missing env var, e.g.os.getenv("JWT_SECRET", "")),encode/decodewill now raiseInvalidKeyError. This is the intended behavior — fix the configuration.PyJWKdecoding now requires the token'salgto match the JWK's algorithm. Previously a mismatch was silently honored if the headeralgappeared in the allow-list. Tokens that relied on this mismatch will now fail withInvalidAlgorithmError.PyJWKClientnow rejects non-HTTP(S) URIs at construction time. Tests or dev environments that fetched JWKS fromfile://URIs need to switch to a local HTTP server or load the JWKS by other means (e.g. constructPyJWKSet.from_dict(...)directly).b64=falsetokens are now strictly RFC 7515 / 7797 compliant. Tokens with a non-empty compact-form payload segment, or that omit"b64"fromcrit, will be rejected. PyJWT-produced tokens always satisfy both invariants, so round-trips through PyJWT are unaffected.enforce_minimum_key_lengthset per-call now takes effect. Callers who passedoptions={"enforce_minimum_key_length": True}tojwt.decode()previously got no enforcement; they will now getInvalidKeyErroron undersized keys, as documented.Full changelog: https://github.com/jpadilla/pyjwt/compare/2.12.1...2.13.0
Changelog
Sourced from pyjwt's changelog.
v2.15.0 <https://github.com/jpadilla/pyjwt/compare/2.14.0...2.15.0>__Security
- Wrap recursion errors from deeply nested JWT payloads in ``DecodeError`` instead of exposing a raw ``RecursionError``.Added
- Support Python 3.15 by @kytta in `[#1202](https://github.com/jpadilla/pyjwt/issues/1202) <https://github.com/jpadilla/pyjwt/pull/1202>`__
Changed
JWKSetCachenow stores the parsedPyJWKSetrather than the raw JWKS payload, so a cache hit no longer re-parses every key.JWKSetCache.put()accepts either form and raisesPyJWKSetErrorfor anything else. As a result,PyJWKClient.get_jwk_set()returns the samePyJWKSetinstance for as long as it stays cached, rather than a freshly built one per call in[#1208](https://github.com/jpadilla/pyjwt/issues/1208) <https://github.com/jpadilla/pyjwt/pull/1208>__PyJWKClient.fetch_data()now raisesPyJWKClientError("The JWKS endpoint did not return a JSON object")when the endpoint response is not a JSON object, instead of returning it forget_jwk_set()to reject. Callers reaching the JWKS throughget_jwk_set()see the same error as before in[#1208](https://github.com/jpadilla/pyjwt/issues/1208) <https://github.com/jpadilla/pyjwt/pull/1208>__Fixed
- Return cached ``PyJWKSet`` values from ``PyJWKClient.get_jwk_set()`` instead of raising ``PyJWKClientError("The JWKS endpoint did not return a JSON object")``. ``JWKSetCache.put()`` documents ``PyJWKSet`` as the cached value, so callers pre-populating the cache to avoid a network round-trip could not read it back in `[#914](https://github.com/jpadilla/pyjwt/issues/914) <https://github.com/jpadilla/pyjwt/issues/914>`__ and `[#1208](https://github.com/jpadilla/pyjwt/issues/1208) <https://github.com/jpadilla/pyjwt/pull/1208>`__ - ``PyJWKClient.get_jwk_set()`` now caches the key set it returns, so a ``fetch_data()`` override that filters or transforms the JWKS is no longer undone by the next cache hit in `[#1208](https://github.com/jpadilla/pyjwt/issues/1208) <https://github.com/jpadilla/pyjwt/pull/1208>`__ - Raise the documented ``PyJWTError`` subclass instead of leaking a ``TypeError`` when the ``exp``, ``nbf``, or ``iat`` claim decodes to a non-numeric, non-string value such as a list, dict, or ``null``. - Reject OKP JWK private keys when their public ``x`` component does not match the private ``d`` component. - Treat malformed JWK Set members as unusable keys rather than letting ``AttributeError`` or ``TypeError`` escape ``PyJWKSet``. A member that is not </tr></table> </code></pre> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary><ul>
<li><a href="https://github.com/jpadilla/pyjwt/commit/1d41a6478e1562e68ff667fcd703356acf085f68"><code>1d41a64</code></a> chore: prepare 2.15.0 release</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/9bc06658f875b9b40091539140bbbdc4639161c3"><code>9bc0665</code></a> fix: make recursive payload tests deterministic</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/5fde08a6cf906aa7698de2d6391d88b73006b17b"><code>5fde08a</code></a> fix: normalize recursive JWT payload errors</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/171062d2d734315272a901100aa4b109f2fc3c19"><code>171062d</code></a> utils: mention bytes in force_bytes type error (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1173">#1173</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/c9d4d5375bf464ef363506fed9eb6e7f33217ab6"><code>c9d4d53</code></a> docs/conf: drop duplicate 'and' from read() docstring (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1174">#1174</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/2763752196113e1473b0ed7905aa6034aedfbe53"><code>2763752</code></a> Add support for Python 3.15 (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1202">#1202</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/4adcd02722f5011c60079d3978dfc167b9a8eaa5"><code>4adcd02</code></a> Catch http.client.HTTPException in PyJWKClient.fetch_data (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1201">#1201</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/9e501d993b4d3e7dba14bdb1722b1d993ac75097"><code>9e501d9</code></a> fix: correct docstring typo in _validate_jti (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1179">#1179</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/4047c44d51950ffda15f40054508d3f17c43b1e2"><code>4047c44</code></a> docs: clarify JWK certificate member handling (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1212">#1212</a>)</li>
<li><a href="https://github.com/jpadilla/pyjwt/commit/f4e2b59f543cc82d46d9d69922bba59e804216b9"><code>f4e2b59</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/jpadilla/pyjwt/issues/1210">#1210</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/jpadilla/pyjwt/compare/2.12.1...2.15.0">compare view</a></li>
</ul>
</details>
<br />Updates
urllib3from 2.7.0 to 2.8.0Release notes
Sourced from urllib3's releases.
2.8.0
🚀 urllib3 is fundraising for HTTP/2 support
urllib3 is raising ~$40,000 USD to release HTTP/2 support and ensure long-term sustainable maintenance of the project. If your company or organization uses Python and would benefit from HTTP/2 support in Requests, pip, cloud SDKs, and thousands of other projects please consider contributing financially to ensure HTTP/2 support is developed sustainably and maintained for the long-haul.
Thank you for your support.
Security
Fixed the following security issues:
- The TLS configuration for HTTPS proxies could be ignored or overridden. (High severity, GHSA-8988-9cw3-xx77)
HTTPResponse.stream()andread_chunked()could buffer a chunk-size line of unbounded length in memory. (High severity, GHSA-vxq7-64xx-v4gw)- Chunked Deflate streaming could enter an infinite loop. (Medium severity, GHSA-gh4c-6fx4-qh6g)
[!IMPORTANT] urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or overridden by destination settings. Configurations relying on that behavior may require changes.
Configure proxy CA certificates and client certificates in
proxy_ssl_context, and proxy identity checks withproxy_assert_hostnameorproxy_assert_fingerprint. Destination client certificates and identity overrides no longer apply to HTTPS forwarding proxy connections.[!NOTE] CVE IDs had not yet been assigned to these advisories at the time of release due to a backlog at GitHub's CNA.
Deprecations & Removals
- Deprecated using an empty collection as the
Retryoptionallowed_methodsto retry any verb. (#5044)Features
- Added
Url.auth_decodedandUrl.auth_decoded_joinedconvenience properties to the result ofparse_url(). (#4945)- Added
basic_auth_encodingandproxy_basic_auth_encodingparameters tourllib3.util.make_headers(). (#5092)Bugfixes
Fixed response header handling to replace obsolete folded header lines (
obs-fold) with spaces in accordance with RFC 9112, preventing raw CRLF sequences from appearing in header values such asSet-Cookie. (#1362)Fixed usage of
proxy_ssl_contextwithProxyManagerwhenuse_forwarding_for_https=True. Passingssl_contextinstead ofproxy_ssl_contextfor HTTPS proxies in this configuration now emits aFutureWarningand will raise an error in v3.0. (#2577)Changed behavior of the default
ConnectionPool.poolinitialization.LifoQueueis now resolved from thequeuemodule after theConnectionPoolis instantiated instead of using the default cachedQueueClsclass property. This is done because sometimes thequeue.LifoQueueis monkey-patched late in the program, such as by gevent. (#3289)Raised
UnrewindableBodyErrorinstead ofValueErrorwhen retrying a request whose body hadtell()but notseek(). (#3779)Decoded percent-encoded SOCKS proxy credentials before authenticating with the proxy server. (#3785)
Fixed
HTTPResponse.drain_conn()to discard unread response data in 64 KiB chunks (same as the defaultamtwhen doingHTTPResponse.stream(...)). (#5019)Fixed
is_ipaddress()to detect non-standard IPv4 forms accepted bysocket.connect, such as hex (0x7f000001), octal (0177.0.0.1), and decimal integers (2130706433), ensuring SSL certificate verification uses the correct mode for these addresses. (#5029)Fixed
HTTPConnectionPool.urlopenraising a misleadingFullPoolErrorinstead ofValueErrorwhen called with an invalidtimeoutargument on a pool created withblock=True. (#5059)Fixed port-zero handling to preserve explicit
:0values instead of substituting the default ports 80 or 443 in URL parsing, pool selection, proxy configuration,connection_from_url(), and HTTP/2 request authority. (#5071, #5101)Fixed a bug where
PoolManagerpassed theassert_hostnameandassert_fingerprintparameters to HTTP connection pools. (#5077)Fixed
HTTPConnectionPool.urlopen()and HTTP proxy forwarding to strip URL fragments from absolute request targets before sending requests. (#5079)Added safeguards to the proxy tunneling code to prevent potential security issues when handling invalid characters in the proxy host and HTTP headers. This change affects users of Python 3.10, Python 3.11, and Python 3.12 when the standard library does not contain the fix; those on newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the same security fixes. (#5091)
Fixed
HTTPSConnection.connect()overridingProxyConfig.ssl_context's certificate policy and proxy identity checks with the target connection's TLS settings when forwarding through an HTTPS proxy.
HTTPSConnectionno longer applies target SNI, assertions, or client credentials to forwarding proxy handshakes and continues to use itsssl_contextas a fallback when an HTTPS proxy forwards an HTTP target. (#5093)Fixed URL parsing to more strictly enforce RFC 3986 host syntax, rejecting invalid host input such as raw spaces and control characters, malformed percent-encodings, and percent-encoded control characters in HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel targets. Host normalization now also follows RFC 3986 normalization rules for percent-encoded octets by decoding percent-encoded unreserved characters and uppercasing the hexadecimal digits of retained percent-encoded octets. (#5095)
... (truncated)
Changelog
Sourced from urllib3's changelog.
2.8.0 (2026-09-15)
Security
Fixed the following security issues:
- The TLS configuration for HTTPS proxies could be ignored or overridden. (High severity,
GHSA-8988-9cw3-xx77 <https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77>__)HTTPResponse.stream()andread_chunked()could buffer a chunk-size line of unbounded length in memory. (High severity,GHSA-vxq7-64xx-v4gw <https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw>__)- Chunked Deflate streaming could enter an infinite loop. (Medium severity,
GHSA-gh4c-6fx4-qh6g <https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g>__).. caution::
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or overridden by destination settings. Configurations relying on that behavior may require changes.
Configure proxy CA certificates and client certificates inproxy_ssl_context, and proxy identity checks withproxy_assert_hostnameorproxy_assert_fingerprint. Destination client certificates and identity overrides no longer apply to HTTPS forwarding proxy connections.Deprecations & Removals
- Deprecated using an empty collection as the
Retryoptionallowed_methodsto retry any verb. ([#5044](https://github.com/urllib3/urllib3/issues/5044) <https://github.com/urllib3/urllib3/issues/5044>__)Features
- Added
Url.auth_decodedandUrl.auth_decoded_joinedconvenience properties to the result ofparse_url(). ([#4945](https://github.com/urllib3/urllib3/issues/4945) <https://github.com/urllib3/urllib3/issues/4945>__)- Added
basic_auth_encodingandproxy_basic_auth_encodingparameters tourllib3.util.make_headers(). ([#5092](https://github.com/urllib3/urllib3/issues/5092) <https://github.com/urllib3/urllib3/issues/5092>__)Bugfixes
... (truncated)
Commits
b1d30abRelease 2.8.09016d7eSkiptest_read_chunked_with_trailing_data_does_not_hangfor brotlicffi (#5258)9101f58Fixnox -s docswarning (#5256)cd770b0Merge commit from forkea2ad7bMerge commit from fork0716e31Fix loading unencrypted client keys with a password in pyOpenSSL (#5255)43c68c8Test pickling ofInvalidChunkLength(#5247)308b279Share security policy between GitHub and Read the Docs (#5253)53fa073Add policy on duplicate pull requests (#5252)5f2a6a8Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (#5232)- Additional commits viewable in compare view
Updates
pyjwtfrom 2.13.0 to 2.15.0Release notes
Sourced from pyjwt's releases.
2.15.0
See the 2.15.0 changelog for complete release details.
2.14.0
See the 2.14.0 changelog for the complete release details and related security advisories.
2.13.0
PyJWT 2.13.0 — Security Release
This release bundles five security fixes plus three additional hardening / spec-compliance changes. We recommend all users upgrade.
Security
GHSA-xgmm-8j9v-c9wx— JWK JSON accepted as HMAC secret (algorithm confusion).HMACAlgorithm.prepare_keypreviously rejected PEM- and SSH-formatted asymmetric keys but did not catch a JWK passed as a raw JSON string. In a verifier configured with both symmetric and asymmetric algorithms inalgorithms=[…]and a raw-JSON JWK as the key, an attacker could forge HS256 tokens using the JWK text as the HMAC secret. The guard has been extended to reject any JWK-shaped JSON. Reported by@aradona91.
GHSA-jq35-7prp-9v3f— Algorithm allow-list bypass withPyJWK/PyJWKClient. When verifying with aPyJWK, the caller'salgorithms=[…]allow-list was checked against the token headeralgas a string only; actual verification used the algorithm bound to thePyJWK. An attacker who controlled a registered JWKS key could sign with one algorithm and advertise another on the header. PyJWT now requires the token headeralgto match thePyJWK's algorithm before verification. Reported by@sushi-gif.
GHSA-w7vc-732c-9m39— DoS via base64 decode of unused payload segment whenb64=false. For detached-payload JWS (b64=false), the compact-form payload segment was base64-decoded before being discarded in favor of the caller-supplieddetached_payload. An attacker could inflate the unused segment to force CPU + memory cost without holding a valid signature. The segment is now required to be empty per RFC 7515 Appendix F, and is no longer decoded. Reported by@thesmartshadow.
GHSA-993g-76c3-p5m4—PyJWKClientaccepts non-HTTP(S) URIs.PyJWKClient.fetch_datapassed its URI tourllib.request.urlopen, which by default also handlesfile://,ftp://, anddata:schemes. An application that fed an attacker-influenced URI intoPyJWKClientcould be coerced into reading local files or reaching other unintended schemes.PyJWKClientnow rejects any URI whose scheme isn'thttporhttps. Reported by@KEIJOT.
GHSA-fhv5-28vv-h8m8—PyJWKClientcache wiped on fetch error. Afinally-blockput(jwk_set=None)cleared the JWK Set cache whenever a fetch raised, turning a transient JWKS-endpoint outage into application-wide auth failure. The cache write was moved into the success path; transient errors no longer evict valid cached keys. Reported by@eddieran.Fixed
- Reject empty HMAC keys outright in
HMACAlgorithm.prepare_keywithInvalidKeyErrorinstead of accepting them with only a warning. Defends against theos.getenv("JWT_SECRET", "")footgun. Thanks to@SnailSploitand@spartan8806for the reports.- Forward per-call
options(includingenforce_minimum_key_length) fromPyJWT.decodethrough toPyJWS._verify_signature. The option was previously silently dropped between the two layers, so it only took effect when set on thePyJWTinstance. Thanks to@WLUBfor the report.- RFC 7797 §3 compliance for
b64=false: the encoder now auto-adds"b64"tocrit, and the decoder rejects tokens that setb64=falsewithout listing it incrit. Thanks to@MachineLearning-Nerdfor the report.Changed
- Migrate the
dev,docs, andtestspackage extras to dependency groups, by@kurtmckeein #1152.Upgrade notes
Most fixes are invisible to correctly-configured callers. A few behavioral changes you may encounter:
- Empty HMAC keys now raise. If your app passed
""orb""as a secret (often via a missing env var, e.g.os.getenv("JWT_SECRET", "")),encode/decodewill now raiseInvalidKeyError. This is the intended behavior — fix the configuration.PyJWKdecoding now requires the token'salgto match the JWK's algorithm. Previously a mismatch was silently honored if the headeralgappeared in the allow-list. Tokens that relied on this mismatch will now fail withInvalidAlgorithmError.PyJWKClientnow rejects non-HTTP(S) URIs at construction time. Tests or dev environments that fetched JWKS fromfile://URIs need to switch to a local HTTP server or load the JWKS by other means (e.g. constructPyJWKSet.from_dict(...)directly).b64=falsetokens are now strictly RFC 7515 / 7797 compliant. Tokens with a non-empty compact-form payload segment, or that omit"b64"fromcrit, will be rejected. PyJWT-produced tokens always satisfy both invariants, so round-trips through PyJWT are unaffected.enforce_minimum_key_lengthset per-call now takes effect. Callers who passedoptions={"enforce_minimum_key_length": True}tojwt.decode()previously got no enforcement; they will now getInvalidKeyErroron undersized keys, as documented.Full changelog: https://github.com/jpadilla/pyjwt/compare/2.12.1...2.13.0
Changelog
Sourced from pyjwt's changelog.
v2.15.0 <https://github.com/jpadilla/pyjwt/compare/2.14.0...2.15.0>__Security
- Wrap recursion errors from deeply nested JWT payloads in ``DecodeError`` instead of exposing a raw ``RecursionError``.Added
- Support Python 3.15 by @kytta in `[#1202](https://github.com/jpadilla/pyjwt/issues/1202) <https://github.com/jpadilla/pyjwt/pull/1202>`__
Changed
JWKSetCachenow stores the parsedPyJWKSetrather than the raw JWKS payload, so a cache hit no longer re-parses every key.JWKSetCache.put()accepts either form and raisesPyJWKSetErrorfor anything else. As a result,PyJWKClient.get_jwk_set()returns the samePyJWKSetinstance for as long as it stays cached, rather than a freshly built one per call in[#1208](https://github.com/jpadilla/pyjwt/issues/1208) <https://github.com/jpadilla/pyjwt/pull/1208>__PyJWKClient.fetch_data()now raisesPyJWKClientError("The JWKS endpoint did not return a JSON object")when the endpoint response is not a JSON object, instead of returning it forget_jwk_set()to reject. Callers reaching the JWKS throughget_jwk_set()see the same error as before in[#1208](https://github.com/jpadilla/pyjwt/issues/1208) <https://github.com/jpadilla/pyjwt/pull/1208>__...Description has been truncated