Listen to this Post
PyJWT 2.13.0 added HMACAlgorithm.prepare_key() guard at jwt/algorithms.py near line 344.
The guard is intended to stop RSA public key material from being used as an HMAC secret.
This issue is tracked as CVE-2026-48526.
The guard reads key bytes and calls bytes.lstrip() before checking startswith(b”{“).
bytes.lstrip() with no argument removes only ASCII whitespace bytes.
Those bytes are \x20, \t, \n, \r, \x0b, and \x0c.
A UTF-8 BOM prefix \xef\xbb\xbf is not ASCII whitespace.
Therefore lstrip() leaves a BOM-prefixed JWK JSON unchanged at the front.
Then stripped.startswith(b”{“) returns False.
The JWK detection block is skipped.
The RSA public key bytes are accepted as an HMAC-SHA256 secret.
An attacker can obtain the RSA public key JWK from a JWKS endpoint or certificate.
The key is public by design.
The attacker prepends a UTF-8 BOM before the JSON opening brace.
The attacker signs a JWT using HS256 with the BOM-prefixed JWK as secret.
The forged token contains arbitrary claims such as role or sub.
The attacker submits the token to a verifier.
The verifier must accept algorithms=[“HS256”, “RS256”] or equivalent mixed set.
The verifier must hold the same RSA public key as raw bytes.
PyJWT 2.13.0 accepts the token because the BOM bypasses JWK detection.
The RSA JWK bytes become a valid HMAC key.
The verifier trusts the forged HS256 token.
This is an algorithm-confusion bypass.
It is also a patch bypass for CVE-2026-48526.
Users who upgraded to 2.13.0 remain vulnerable.
The fix commit is 180783930de91876bc0d601f826a1f2956057291.
HMACAlgorithm.prepare_key() now checks parsed JSON objects for kty.
It handles accepted UTF-8/16/32 representations.
It preserves non-JWK HMAC key bytes.
It conservatively rejects deeply nested JSON objects.
The fix is included in PyJWT 2.14.0, released on 2026-09-11.
DailyCVE Form:
Platform: PyJWT
Version: 2.13.0
Vulnerability : JWT algorithm confusion
Severity: High
date: 2026-09-11
Prediction: 2026-09-11
(end of form)
What Undercode Say:
Analytics:
python -c "import jwt; print(jwt.<strong>version</strong>)" pip show pyjwt python -c "import jwt, os; print(os.path.dirname(jwt.<strong>file</strong>))" grep -n "prepare_key" $(python -c "import jwt, os; print(os.path.dirname(jwt.<strong>file</strong>))")/algorithms.py sed -n '330,360p' $(python -c "import jwt, os; print(os.path.dirname(jwt.<strong>file</strong>))")/algorithms.py
from jwt.algorithms import HMACAlgorithm
key_bytes = b'\xef\xbb\xbf{"kty":"RSA","n":"...","e":"AQAB"}'
stripped = key_bytes.lstrip()
print(stripped.startswith(b"{")) False in PyJWT 2.13.0
Exploit: (Educational Purposes!)
PoC sketch only — not weaponized
import jwt
public_jwk = b'\xef\xbb\xbf{"kty":"RSA","n":"...","e":"AQAB"}'
forged = jwt.encode({"sub": "admin", "role": "admin"}, public_jwk, algorithm="HS256")
jwt.decode(forged, public_jwk, algorithms=["HS256", "RS256"])
curl -s https://target.example/.well-known/jwks.json
Protection: from this CVE
pip install --upgrade PyJWT==2.14.0
import jwt from jwt import PyJWK Avoid mixed algorithms jwt.decode(token, rsa_public_key, algorithms=["RS256"]) Use algorithm-bound PyJWK key = PyJWK.from_json(jwk_json).key jwt.decode(token, key, algorithms=["RS256"])
import json
from jwt.exceptions import InvalidKeyError
BOM_PREFIXES = (b"\xef\xbb\xbf", b"\xff\xfe", b"\xfe\xff")
stripped = key_bytes
for bom in BOM_PREFIXES:
if stripped.startswith(bom):
stripped = stripped[len(bom):]
break
stripped = stripped.lstrip()
try:
test_obj = json.loads(key_bytes.strip())
if isinstance(test_obj, dict) and "kty" in test_obj:
raise InvalidKeyError("The specified key is an asymmetric key...")
except (ValueError, UnicodeDecodeError):
pass
Impact:
Complete authentication and authorization bypass. C:H/I:H, AC:H, PR:N, UI:N, S:U, A:N. CVSS 3.1 score 7.4. CWE-347. Patch bypass for CVE-2026-48526. PyJWT 2.14.0 is patched version.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

