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-48526

CVE-2026-48526: Algorithm Confusion Vulnerability in PyJWT

Alon Barad
Alon Barad
Software Engineer

Jun 4, 2026·7 min read·122 visits

Executive Summary (TL;DR)

An algorithm-confusion vulnerability in PyJWT allows remote attackers to bypass authentication by signing forged tokens with a public JWK string treated as a symmetric HMAC secret.

CVE-2026-48526 is an algorithm-confusion vulnerability in PyJWT prior to version 2.13.0. When an application decodes tokens using a raw JSON Web Key (JWK) string while simultaneously supporting mixed algorithm families (symmetric and asymmetric), PyJWT does not validate that the key matches its intended algorithm context. This allows an attacker to sign a forged token using the public JWK string as an HMAC symmetric secret, bypassing authentication controls.

Vulnerability Overview

JSON Web Tokens (JWT) are widely adopted for stateless authentication and authorization in web applications. To maintain security, verifying applications must ensure that tokens are validated using the correct cryptographic algorithm and key. The pyjwt library provides token encoding and decoding functionality for Python applications.

CVE-2026-48526 identifies a critical algorithm-confusion vulnerability in pyjwt before version 2.13.0. The flaw manifests when an application validates tokens using keys supplied as raw JSON Web Key (JWK) strings and supports mixed algorithm families, such as allowing both asymmetric RS256 and symmetric HS256 validation. In this scenario, the library fails to validate that the key material matches the chosen algorithm family.

An attacker with access to the public JWK can sign a forged token using the raw JWK JSON string as the HMAC symmetric secret. The target backend processes the forged token with the HS256 algorithm, uses the public JWK string as the symmetric key, and successfully verifies the signature. This behavior enables a complete authentication bypass and unauthorized privilege escalation.

Root Cause Analysis

The root cause of CVE-2026-48526 lies in the key preparation phase of pyjwt's signature verification logic. To prevent traditional algorithm-confusion attacks, the library verifies that keys passed to the HMACAlgorithm class are not PEM-formatted or SSH public keys. This validation is designed to prevent asymmetric public keys from being interpreted as symmetric HMAC secrets.

However, this defense relies on the assumption that public keys are only provided in PEM or SSH formats. Public keys represented as structured JSON Web Keys (JWK) bypass this validation because they do not contain the typical header and footer markers of PEM or SSH keys. Consequently, the HMACAlgorithm class accepts the raw byte representation of a JWK JSON document as a valid HMAC secret.

When a developer configures an application to accept both symmetric and asymmetric algorithms (mixed families) and passes a raw JWK string to the decoder, a logical vulnerability is introduced. The application delegates the selection of the verification algorithm to the 'alg' header of the incoming token. If the token specifies an HMAC algorithm like HS256, the library utilizes the HMAC path and treats the raw JWK string as the HMAC shared secret.

Code Analysis

Prior to version 2.13.0, the prepare_key method in jwt/algorithms.py processed keys without checking for structured JSON metadata. The function received the key, converted it to bytes, and performed basic PEM and SSH checks. Below is the vulnerable implementation of the method:

# Vulnerable implementation in jwt/algorithms.py
def prepare_key(self, key: str | bytes) -> bytes:
    key_bytes = force_bytes(key)
 
    if is_pem_format(key_bytes) or is_ssh_key(key_bytes):
        raise InvalidKeyError(
            "The specified key is an asymmetric key or x509 certificate and"
            " should not be used as an HMAC secret."
        )
 
    return key_bytes

The fix introduced in commit 95791b1759b8aa4f2203575d344d5c78564cdc81 enhances the validation mechanism. It strips leading whitespace and determines if the input byte sequence begins with the character {, which indicates a JSON payload. If the string is valid JSON and contains the 'kty' (key type) key, the library rejects the key to prevent its use as an HMAC secret.

# Patched implementation in jwt/algorithms.py
def prepare_key(self, key: str | bytes) -> bytes:
    key_bytes = force_bytes(key)
 
    if len(key_bytes) == 0:
        raise InvalidKeyError("HMAC key must not be empty.")
 
    if is_pem_format(key_bytes) or is_ssh_key(key_bytes):
        raise InvalidKeyError(
            "The specified key is an asymmetric key or x509 certificate and"
            " should not be used as an HMAC secret."
        )
 
    stripped = key_bytes.lstrip()
    if stripped.startswith(b"{"):
        try:
            jwk_obj = json.loads(key_bytes)
        except ValueError:
            jwk_obj = None
        if isinstance(jwk_obj, dict) and "kty" in jwk_obj:
            raise InvalidKeyError(
                "The specified key looks like a JWK and should not be "
                "used directly as an HMAC secret. Load it via "
                "PyJWK / HMACAlgorithm.from_jwk first."
            )
 
    return key_bytes

Exploitation Methodology

Exploiting CVE-2026-48526 requires three primary conditions. First, the application must verify tokens using a list of mixed algorithms (e.g., RS256 and HS256). Second, the application must pass the raw JSON JWK string directly as the verification key. Third, the attacker must have access to the exact JSON representation of the public JWK, which is standard for public JWK endpoints.

The attacker retrieves the public JWK from the victim server's public key endpoint. Next, the attacker constructs a malicious payload, setting the 'alg' header to 'HS256' and modifying claims to escalate privileges. Using the raw public JWK JSON string as the symmetric key, the attacker signs the token using HMAC-SHA256. Upon receiving the token, pyjwt sees the 'HS256' algorithm, retrieves the public JWK string, and performs symmetric verification. The signatures match, bypassing authentication.

In-Depth Security Analysis & Potential Bypasses

While the implemented defense-in-depth patch significantly reduces the attack surface, security analysis reveals potential gaps in the validation logic. One notable gap is Byte Order Mark (BOM) confusion. The patched code calls key_bytes.lstrip() to remove leading standard ASCII whitespace before checking if the string starts with b'{'. If a JWK contains a Unicode BOM, such as a UTF-8 BOM, the startswith check evaluates to False, bypassing the JSON check while still being decodable by standard JSON libraries.

Another critical bypass vector involves JSON Web Key Sets (JWKS). The patch evaluates whether the decoded JSON object is a dictionary containing the 'kty' key. However, public keys are frequently distributed within a JWKS, which wraps multiple JWK objects inside a 'keys' list. If a developer incorrectly passes a full JWKS JSON string to the decoder, the parsed object is a dictionary but contains 'keys' instead of 'kty', bypassing the check.

These edge cases highlight the limitations of signature-based or format-based heuristics. They emphasize that security controls must not rely on parsing structure to determine key validity. Instead, applications must enforce strict separation of algorithm families and validate keys using cryptographic typing.

Remediation & Mitigation Guidance

The primary remediation for CVE-2026-48526 is upgrading the pyjwt library to version 2.13.0 or later. This upgrade integrates the JSON verification check within the key preparation process, preventing raw JWKs from being misinterpreted as HMAC secrets. Ensure that all dependency files are updated and redeployed across target environments.

In addition to upgrading, developers must implement secure key handling practices. Avoid using mixed algorithm families within the same verification path. If an endpoint is designed to process tokens signed with asymmetric keys, restrict the accepted algorithms strictly to asymmetric protocols like RS256. This prevents the library from falling back to symmetric verification paths.

# Secure configuration using PyJWK
from jwt import PyJWK
 
jwk_dict = {"kty": "RSA", "n": "...", "e": "AQAB"}
jwk_obj = PyJWK(jwk_dict)
 
# Secure decoding
jwt.decode(token, jwk_obj.key, algorithms=["RS256"])

Lastly, ensure that raw JWK JSON strings are never passed directly to jwt.decode(). Use the structured PyJWK class to explicitly deserialize the JSON into a cryptographic key object prior to verification. This forces the library to evaluate the key context before signature verification, rendering algorithm-confusion attacks ineffective.

Official Patches

jpadillaFix algorithm confusion with raw JWKs in HMACAlgorithm
jpadillaGHSA Security Advisory for pyjwt

Fix Analysis (1)

Technical Appendix

CVSS Score
7.4/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
EPSS Probability
0.02%
Top 96% most exploited

Affected Systems

pyjwt (Python JSON Web Token Library)

Affected Versions Detail

Product
Affected Versions
Fixed Version
pyjwt
jpadilla
< 2.13.02.13.0
AttributeDetail
CWE IDCWE-287
Attack VectorNetwork
CVSS7.4
EPSS Score0.00017
ImpactHigh
Exploit StatusProof-of-Concept
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1078Valid Accounts
Initial Access
T1190Exploit Public-Facing Application
Initial Access
CWE-287
Improper Authentication

The system does not prove or insufficiently proves that an identity claim is correct.

Vulnerability Timeline

Vulnerability patched and PyJWT version 2.13.0 released.
2026-05-21

References & Sources

  • [1]NVD - CVE-2026-48526
  • [2]CVE-2026-48526 Record

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.

More Reports

•about 1 hour ago•CVE-2026-82395
5.3

CVE-2026-82395: Insecure Direct Object Reference (IDOR) in Sulu CMS Media Move Authorization

Sulu CMS, an open-source PHP content management system based on the Symfony framework, is affected by an Insecure Direct Object Reference (IDOR) vulnerability within its media relocation API. Authenticated users with restricted edit permissions can relocate media out of secure, unauthorized collections into folders they control, bypassing access controls entirely. This security issue is tracked under CVE-2026-82395 and GHSA-h6cx-gjxx-v25c.

Amit Schendel
Amit Schendel
3 views•6 min read
•about 2 hours ago•GHSA-WWV5-G3V4-889X
2.3

GHSA-wwv5-g3v4-889x: Cookie Attribute Injection in Tornado via Legacy Case-Insensitive kwargs

An incomplete sanitization fix for CVE-2026-35536 in Tornado allowed cookie attribute injection. The framework's validation loop checked lowercase keyword arguments but neglected legacy case-insensitive parameters passed through arbitrary keyword arguments, which Python's underlying library parses case-insensitively.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 3 hours ago•GHSA-8423-8FGW-73VQ
5.3

GHSA-8423-8FGW-73VQ: Memory Amplification Denial of Service in Tornado Multipart Form Parser

GHSA-8423-8FGW-73VQ is a pre-authentication denial of service vulnerability in the Tornado web server's handling of multipart/form-data. The flaw allows an unauthenticated remote attacker to cause memory exhaustion and CPU starvation by transmitting a crafted HTTP request containing a high density of boundary delimiters. Because Tornado splits the entire request body in memory prior to enforcing the max_parts validation threshold, the Python interpreter attempts to materialize a massive list of byte segments. This triggers an immediate memory exhaustion (OOM) crash or server-wide CPU starvation before the payload can be validated and rejected.

Alon Barad
Alon Barad
2 views•6 min read
•about 4 hours ago•GHSA-J8PM-GJ4C-RQ4X
7.5

GHSA-J8PM-GJ4C-RQ4X: Algorithmic Complexity Denial of Service in league/commonmark

The league/commonmark library is subject to multiple denial of service vulnerabilities. These stem from three independent algorithmic complexity weaknesses in Markdown parsing: regular expression backtracking, reference link normalization, and delimiter processing. Remote, unauthenticated attackers can exploit these flaws by submitting crafted Markdown input to exhaust CPU execution resources, leading to application-wide thread exhaustion.

Amit Schendel
Amit Schendel
2 views•6 min read
•about 5 hours ago•GHSA-F8FG-PG57-V4J8
5.8

GHSA-f8fg-pg57-v4j8: Sanitizer Filter Bypass via Control Character Injection in league/commonmark

An inconsistency in whitespace handling between the PCRE regex engine, PHP's native trim function, and web browsers allows unauthenticated attackers to bypass XSS protections in the league/commonmark AttributesExtension by injecting a Form Feed (U+000C) control character.

Alon Barad
Alon Barad
2 views•7 min read
•about 6 hours ago•GHSA-JJV6-8J6V-6J52
7.5

GHSA-JJV6-8J6V-6J52: Algorithmic Complexity Denial of Service in league/commonmark

GHSA-JJV6-8J6V-6J52 details multiple algorithmic complexity issues in the SmartPunct and Attributes extensions of the league/commonmark PHP library, leading to high CPU consumption and Denial of Service (DoS) when parsing pathological Markdown inputs.

Amit Schendel
Amit Schendel
4 views•7 min read