CVE-2026-48523
Medium · 5.4CVSS
5.4
EPSS
0.2%
Published
May 28, 2026
CISA due date
—
Cloudanix analysis
Some applications may accept login tokens signed in a way the organization meant to block, allowing unauthorized access if an attacker can supply a trusted signing key.
- Exploitation
- Remote Authenticated
- Attacker needs
- Low Privilege
- Complexity
- Low
- Impact
- Data Tampering
- Component
- Library
- Class
- Authentication Bypass
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
PyJWT versions 2.9.0 through 2.12.1 contain a verifier-side algorithm allow-list bypass when applications call jwt.decode() or jwt.decode_complete() using a PyJWK key, including the documented PyJWKClient.get_signing_key_from_jwt(...) flow. The JWT header algorithm is compared against the caller-provided allowed algorithms list, but the actual signature verification uses the algorithm associated with the PyJWK object instead of the algorithm declared in the token header. If an attacker can control or register a JWK/JWKS private key, they can sign a token using an algorithm that the application intended to disallow, set the JWT header to an allowed algorithm, and have the token accepted. The result is an authentication or authorization bypass with potential unauthorized access or privilege escalation depending on how JWT claims are trusted by the application.
Why it matters to the business
Applications that rely on affected PyJWT versions for login, API authorization, service-to-service authentication, or tenant/user identity verification may accept tokens that violate the organization’s intended cryptographic policy. The practical impact is unauthorized access to protected application functions or data if an attacker can register or influence a JWK/JWKS key source. Although the CVSS score is moderate and EPSS is currently low, the issue affects a widely used Python JWT library and can be difficult to spot because tokens may appear to use an approved algorithm in their header while being verified under a different algorithm internally.
How an attack unfolds
An attacker first needs a path to introduce or control a JWK/JWKS key that the target application will trust, such as a bring-your-own-key identity integration, a registered client key, federation metadata, or another mechanism that allows attacker-controlled public keys to be fetched by PyJWKClient. The attacker then creates a JWT whose header advertises an algorithm that is present in the application’s allowed algorithms list. Instead of signing with that advertised algorithm, the attacker signs the token with a different algorithm bound to the PyJWK object and normally disallowed by policy. In vulnerable PyJWT versions, the decode path checks the header algorithm against the allow-list but performs signature verification using the algorithm bound to the PyJWK key. If the signature validates under that bound algorithm, the token is accepted. The attacker can then use claims in the accepted token to access data, impersonate an identity, or perform actions allowed to that token subject.
How to fix it
Upgrade PyJWT to version 2.13.0 or later. Treat all PyJWT versions from 2.9.0 through 2.12.1 as affected when used with PyJWK, jwt.decode(), jwt.decode_complete(), or PyJWKClient.get_signing_key_from_jwt(...). Rebuild and redeploy applications, containers, serverless packages, and virtual environments that vendor or pin PyJWT. If immediate upgrade is not possible, avoid using attacker-controllable JWK/JWKS sources, do not allow untrusted parties to register verification keys, enforce strict issuer and audience validation, restrict accepted key IDs to known trusted keys, and independently verify that the JWK key type and algorithm match the application’s expected algorithm before calling decode. Review dependency lockfiles and transitive dependencies to ensure no runtime package still resolves to an affected PyJWT version.
How to confirm the fix worked
Confirm the deployed runtime imports PyJWT 2.13.0 or later, not just that dependency manifests were updated. Validate with package inspection commands such as python -c "import jwt; print(jwt.__version__)" in each deployed artifact or image. Search source code for jwt.decode(), jwt.decode_complete(), PyJWK, and PyJWKClient.get_signing_key_from_jwt(...) to identify affected validation paths. Review dependency lockfiles such as requirements.txt, poetry.lock, Pipfile.lock, uv.lock, conda environment files, container build logs, and SBOMs for PyJWT versions 2.9.0 through 2.12.1. Where feasible, add a regression test using a JWT whose header algorithm differs from the PyJWK-bound algorithm and confirm it is rejected after upgrade. Also confirm JWT validation enforces issuer, audience, expiration, key ID, and expected algorithm constraints consistently.
Typical attack path
- Identify an application or API that validates JWTs using PyJWT 2.9.0 through 2.12.1 with PyJWK or PyJWKClient-based key resolution.
- Find a mechanism to register, publish, or otherwise influence a trusted JWK/JWKS key used by the verifier.
- Generate or control a JWK whose associated algorithm differs from the application’s intended allowed algorithm policy.
- Create a JWT with a header alg value that is allowed by the verifier configuration.
- Sign the JWT using the disallowed algorithm associated with the attacker-controlled PyJWK key.
- Submit the crafted token to the application or API.
- If accepted, use the token’s claims to access protected resources or perform unauthorized actions.
How to detect it
There are no universal network or host indicators for exploitation because abuse occurs through crafted JWTs and normal application authentication flows. Detection should focus on application authentication logs, API gateway logs, identity provider/federation logs, JWKS/key-management audit logs, and application debug/security logs that record JWT metadata. Look for accepted tokens where the JWT header alg differs from the algorithm configured or associated with the JWK used to verify it, unexpected or newly registered key IDs, unrecognized JWKS URLs, unfamiliar issuers, or sudden successful authentication by identities tied to recently added client or federation keys. Review logs for PyJWKClient key fetches from unexpected domains or paths, spikes in token validation failures followed by success, access using newly introduced kid values, and privilege-bearing claims issued outside normal identity-provider flows. If token samples were logged or captured, decode headers and compare alg, kid, iss, aud, and the JWK metadata from the key source at the time of validation. Also perform forensic dependency review to determine whether affected PyJWT versions were present during suspicious authentication events.
What your security team should do
- Prioritize upgrading all applications and services using PyJWT 2.9.0 through 2.12.1 to PyJWT 2.13.0 or later, especially internet-facing APIs and identity/federation components.
- Inventory Python applications, containers, serverless functions, and CI/CD artifacts for PyJWT usage and affected versions.
- Identify code paths that use PyJWKClient.get_signing_key_from_jwt(...), PyJWK, jwt.decode(), or jwt.decode_complete() and review whether keys can be influenced by external parties.
- Restrict trusted JWKS endpoints and key registration workflows; do not accept arbitrary or user-controlled JWK/JWKS material without strong trust validation.
- Harden JWT validation by requiring expected issuer, audience, expiration, key ID, key type, and algorithm consistency checks.
- Review authentication and authorization logs for unusual tokens, unexpected key IDs, unfamiliar issuers, newly registered signing keys, or access patterns associated with newly added federation/client keys.
- Add dependency scanning policy to block PyJWT versions 2.9.0 through 2.12.1 from future builds.
- Because this is not currently listed in CISA KEV and EPSS is low, coordinate remediation through normal high-priority patch cycles unless the application accepts externally managed JWK/JWKS keys, in which case treat as urgent.
The record
PyJWT is a JSON Web Token implementation in Python. From 2.9.0 to 2.12.1, there is a verifier-side algorithm allow-list bypass when jwt.decode() or jwt.decode_complete() are called with a PyJWK key. The token header alg is checked against the caller-supplied algorithms allow-list, but signature verification is performed with the algorithm bound to the PyJWK object instead of the header algorithm. An attacker who controls a registered JWK/JWKS private key can sign with a disallowed algorithm, advertise an allowed algorithm in the JWT header, and still be accepted. The issue affects the documented PyJWKClient.get_signing_key_from_jwt(...) flow. This vulnerability is fixed in 2.13.0.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| openSUSE:Leap 16.0 | python-PyJWT | 0 | 2.12.1-160000.2.1 |
| openSUSE:Tumbleweed | python-PyJWT | 0 | 2.13.0-1.1 |
Related vulnerabilities
- CVE-2026-48522 PyJWT is a JSON Web Token implementation in Python. Also affects python-PyJWT
- CVE-2026-48526 PyJWT is a JSON Web Token implementation in Python. Also affects python-PyJWT
- CVE-2026-48525 PyJWT is a JSON Web Token implementation in Python. Also affects python-PyJWT
- CVE-2026-48524 PyJWT is a JSON Web Token implementation in Python. Also affects python-PyJWT
- CVE-2026-32597 PyJWT is a JSON Web Token implementation in Python. Also affects python-PyJWT
- CVE-2024-53861 PyJWT Issuer field partial matches allowed Also affects python-PyJWT
- CVE-2026-87947 Improper Verification of Cryptographic Signature vulnerability in Drupal SAML SSO… CWE-347
- CVE-2026-84918 Improper Verification of Cryptographic Signature vulnerability in Drupal Monobank payment… CWE-347