CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-32597
7.50.01%

CVE-2026-32597: Critical Header Parameter Validation Bypass in PyJWT

Alon Barad
Alon Barad
Software Engineer

Mar 25, 2026·7 min read·5 visits

PoC Available

Executive Summary (TL;DR)

PyJWT < 2.12.0 ignores the mandatory 'crit' header in JSON Web Tokens. This fail-open behavior violates RFC 7515 and allows attackers to bypass security extensions like MFA enforcement. Update to 2.12.0 immediately.

PyJWT versions prior to 2.12.0 fail to validate the `crit` (Critical) Header Parameter as mandated by RFC 7515. This allows attackers to bypass security policies enforced via custom JWT extensions by supplying tokens with unsupported critical parameters, which the library silently ignores instead of rejecting.

Vulnerability Overview

PyJWT is a widely deployed Python implementation of the JSON Web Token (JWT) standard. The library is responsible for parsing, verifying, and decoding JWTs, including JSON Web Signatures (JWS). A critical component of the JWS specification, defined in RFC 7515 Section 4.1.11, is the crit (Critical) Header Parameter. This parameter lists extensions that the recipient must understand and process to securely consume the token.

According to the RFC, if a recipient does not support or understand any of the extensions listed in the crit array, the token must be explicitly rejected as invalid. Prior to version 2.12.0, PyJWT did not implement any validation logic for the crit header. The library parsed the header dictionary but ignored the crit array entirely during the verification phase.

This implementation oversight results in a fail-open state. Security-critical extensions designed to enforce additional constraints—such as Proof-of-Possession requirements or multi-factor authentication flags—are silently bypassed by the library. This behavior is classified under CWE-345 (Insufficient Verification of Data Authenticity) and CWE-863 (Incorrect Authorization).

Root Cause Analysis

The vulnerability stems from the absence of a validation routine in the JWS decoding pipeline within jwt/api_jws.py. When PyJWT processes an incoming token, it segments the token into its header, payload, and signature components. The library successfully deserializes the base64url-encoded JSON header into a Python dictionary. However, the verification logic strictly focused on cryptographic signature validation and standard claims (like exp, nbf, and iat), omitting the mandatory structural validation of the JWS headers.

When a token contains a crit array, the specification mandates a strict whitelist approach. The parser must iterate through the crit array, check each string against its internally supported feature set, and immediately halt execution if an unknown extension is encountered. Because PyJWT lacked this iteration and comparison logic, any validly signed token would be accepted, regardless of the unhandled requirements stipulated by the token producer.

This flaw allows a structural desynchronization between token issuers and consumers. An identity provider might issue a token with custom policy constraints embedded in headers, marking them as critical under the assumption that standard-compliant libraries will reject the token if the policies cannot be enforced. PyJWT's failure to respect this contract nullifies the security guarantees provided by the crit specification.

Code Analysis

The remediation introduced in version 2.12.0 adds a dedicated _validate_crit method to the JWS processing logic. The patch explicitly defines a whitelist of supported critical extensions using the _supported_crit set. Currently, only the b64 (RFC 7797) extension is officially supported by the library.

# Added in PyJWT 2.12.0
_supported_crit: set[str] = {"b64"}
 
def _validate_crit(self, headers: dict[str, Any]) -> None:
    crit = headers["crit"]
    if not isinstance(crit, list) or len(crit) == 0:
        raise InvalidTokenError("Invalid 'crit' header: must be a non-empty list")
    for ext in crit:
        if not isinstance(ext, str):
            raise InvalidTokenError("Invalid 'crit' header: values must be strings")
        if ext not in self._supported_crit:
            raise InvalidTokenError(f"Unsupported critical extension: {ext}")
        if ext not in headers:
            raise InvalidTokenError(
                f"Critical extension '{ext}' is missing from headers"
            )

The patched code introduces several strict validation layers. First, it verifies the structural integrity of the crit parameter, ensuring it is a non-empty list. Second, it enforces type constraints by verifying that every element within the list is a string. Third, it implements the core RFC requirement by cross-referencing each element against the _supported_crit whitelist, raising an InvalidTokenError for any unsupported value.

Finally, the logic performs an integrity check to guarantee that the extension declared in the crit array actually exists as a key within the JWS header dictionary. This comprehensive validation ensures compliance with RFC 7515 and prevents the silent bypass of critical security extensions.

Exploitation Methodology

Exploitation requires the attacker to submit a validly signed JWT to a vulnerable application that relies on custom extensions for security enforcement. The attacker crafts a token containing a crit header array that specifies one or more mandatory extensions. These extensions dictate specific processing rules, such as x-enforce-mfa or exp-must-be-verified.

The following proof-of-concept demonstrates how a token with an unsupported critical extension is constructed and subsequently accepted by a vulnerable version of PyJWT. The token is cryptographically signed, meaning the attacker must possess the appropriate signing key or intercept a legitimately signed token from an upstream provider that includes these headers.

import jwt
 
key = "secret"
 
# A token specifying a critical extension 'x-unknown'
header = {
    "alg": "HS256",
    "crit": ["x-unknown"],
    "x-unknown": "must-be-processed"
}
payload = {"sub": "user123", "admin": True}
 
token = jwt.encode(payload, key, algorithm="HS256", headers=header)
 
try:
    # Vulnerable versions return the payload silently.
    decoded = jwt.decode(token, key, algorithms=["HS256"])
    print("Vulnerable: Token with unknown crit extension accepted.")
except jwt.exceptions.InvalidTokenError as e:
    # Patched versions raise an exception.
    print(f"Patched: Token rejected. Error: {e}")

When this token is processed by PyJWT versions prior to 2.12.0, the jwt.decode function successfully returns the payload. The application logic, assuming the underlying library has enforced all constraints specified in the token's header, proceeds with authorization. The failure to reject the token allows the attacker to bypass the intended security policy completely.

Impact Assessment

The vulnerability carries a CVSS v3.1 base score of 7.5 (High), reflected by the vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N. The impact is strictly isolated to integrity, as the vulnerability does not directly expose sensitive data or cause resource exhaustion. However, the integrity compromise translates to severe authorization bypasses depending on the surrounding application architecture.

In architectures where an API gateway or identity provider attaches custom constraints to tokens, this vulnerability allows privilege escalation. For example, an identity provider might inject a crit: ["require-hardware-key"] header into tokens for highly privileged operations. Because PyJWT ignores this header, the backend service processes the token as valid without verifying hardware key attestation, granting the attacker elevated access.

The current EPSS score is 0.00009 (0.91st percentile), indicating a low baseline probability of exploitation in the wild. This low score reflects the prerequisite that an attacker must interact with an application specifically utilizing custom crit extensions for security enforcement. The vulnerability does not allow arbitrary signature forgery; it strictly facilitates the bypass of explicit header-based constraints.

Remediation and Mitigation

The primary remediation for this vulnerability is updating PyJWT to version 2.12.0 or higher. This release contains the complete validation logic required to enforce the strict processing rules mandated by RFC 7515. Development teams must update their dependency management manifests (requirements.txt, Pipfile, pyproject.toml) and deploy the patched version across all environments.

For systems where immediate patching is not feasible, developers must implement manual header validation logic before passing the token to jwt.decode(). This involves utilizing jwt.get_unverified_header() to inspect the token structure independently.

The manual validation routine must extract the crit array from the unverified header and reject the token if the array contains any unrecognized parameters. This temporary workaround effectively mimics the patch logic and prevents the silent bypass of critical extensions until the library can be safely upgraded.

Official Patches

jpadillaGitHub Security Advisory
jpadillaFix Commit

Fix Analysis (1)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
EPSS Probability
0.01%
Top 99% most exploited

Affected Systems

PyJWT versions prior to 2.12.0Python backend services relying on custom JWS critical extensions for authorizationAPI gateways utilizing PyJWT for token validation

Affected Versions Detail

Product
Affected Versions
Fixed Version
pyjwt
jpadilla
< 2.12.02.12.0
AttributeDetail
CWE IDCWE-345, CWE-863
Attack VectorNetwork
CVSS v3.1 Score7.5 (High)
EPSS Score0.00009 (0.91%)
ImpactIntegrity Loss (Authorization Bypass)
Exploit StatusProof of Concept Available
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1068Exploitation for Privilege Escalation
Privilege Escalation
CWE-345
Insufficient Verification of Data Authenticity

Insufficient Verification of Data Authenticity and Incorrect Authorization due to missing structural validation.

Known Exploits & Detection

Security AdvisoryProof of Concept demonstrating the acceptance of unsupported 'crit' headers.

Vulnerability Timeline

Initial disclosure and vendor advisory published (GHSA-752w-5fwx-jx9f).
2026-03-12
PyJWT version 2.12.0 released with the patch.
2026-03-12
CVE-2026-32597 assigned and published to NVD.
2026-03-13

References & Sources

  • [1]GitHub Security Advisory GHSA-752w-5fwx-jx9f
  • [2]Official CVE Record CVE-2026-32597
  • [3]RFC 7515 JSON Web Signature (JWS) - Section 4.1.11

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.