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

CVE-2026-102266: Signature Verification Bypass in PyJWT via Empty JWK

Alon Barad
Alon Barad
Software Engineer

Sep 30, 2026·8 min read·1 visit

Executive Summary (TL;DR)

PyJWT versions 2.13.0 to 2.14.0 fail to validate key lengths on PyJWK paths, allowing attackers to forge tokens with an empty HMAC key if a trusted JWK contains an empty 'k' parameter.

A signature verification bypass vulnerability in PyJWT allows unauthenticated remote attackers to forge JSON Web Tokens when processing JSON Web Key Sets containing an empty symmetric key.

Vulnerability Overview

CVE-2026-102266 represents a signature verification bypass vulnerability in PyJWT, a prominent Python library implementing JSON Web Token (JWT) and JSON Web Signature (JWS) standards. The flaw specifically affects PyJWT versions 2.13.0 up to, but not including, 2.14.0. The bug resides within the signature validation pathway for tokens verified using JSON Web Keys (JWKs) or JSON Web Key Sets (JWKS). Under specific configurations, this allows an unauthenticated remote attacker to bypass cryptographic trust controls and forge arbitrary JWT assertions.

The failure is located in the key handling discrepancy between raw cryptographic keys and keys encapsulated within a PyJWK object. When PyJWT decodes a token using a raw key, it executes input validation checks to prevent the use of weak or empty keys. However, when parsing and processing keys extracted from a PyJWK instance, the verification pipeline bypassed these validation steps. This architectural oversight allowed the verification process to execute using an empty byte-string secret key when a trusted JWK structure contained empty material.

Because the library defaulted to raising warnings instead of exceptions for inadequate key lengths, the verification function proceeded to calculate and validate signatures using an empty HMAC key. Consequently, if an application relies on a JWK Set containing a symmetric key with an empty representation, an offline attacker can construct a valid signature using a null-byte key. This results in complete validation bypass, granting the attacker the ability to inject arbitrary claims and assume unauthorized identities within the application context.

Root Cause Analysis

The root cause of CVE-2026-102266 lies in the dual-path design of the key validation logic inside PyJWT. Historically, PyJWT implemented a validation pipeline for raw cryptographic keys through the prepare_key method of individual algorithm classes. For HMAC algorithms, this method verified that the key length was non-zero and threw an InvalidKeyError if an empty key was provided. This safe-default behavior ensured that any attempt to initialize an HMAC verification operation with a blank key would fail immediately prior to execution.

In contrast, when the verification pipeline utilized a PyJWK key representation (often dynamically resolved from JWK Sets), the code bypassed this central validation checkpoint. Instead of invoking the algorithm's specialized prepare_key method, the JWS verification layer directly retrieved the raw internal key buffer from the PyJWK object. If the source JWK entry was a symmetric oct key with an empty k parameter, the Base64URL decoding mechanism parsed this parameter into an empty byte string b"" without triggering any initialization errors.

This dual-path vulnerability was compounded by the default handling of key length violations within PyJWT. When the enforce_minimum_key_length configuration option is disabled, which is the default setting, the library only emits an InsecureKeyLengthWarning instead of raising an exception when encountering extremely short keys. Because the empty key path did not trigger an upfront validation failure, the verification function continued its execution path, comparing the incoming signature against an HMAC value generated with a zero-length secret key.

Code Analysis

To understand the mechanics of the vulnerability, we analyze the key loading and signature validation files. The code block below contrasts the vulnerable key loading path in jwt/api_jws.py with the corrected implementation of version 2.14.0. Prior to the fix, the validation logic directly extracted the internal raw key representation from the PyJWK object without invoking the algorithm-specific key preparation logic.

# Vulnerable code in PyJWS._verify_signature (jwt/api_jws.py)
alg_obj = key.Algorithm
prepared_key = key.key  # Bypasses prepare_key validation entirely
 
# Patched code in PyJWS._verify_signature (jwt/api_jws.py)
alg_obj = key.Algorithm
prepared_key = alg_obj.prepare_key(key.key)  # Core Fix: apply prepare_key checks

By replacing key.key with alg_obj.prepare_key(key.key), the patch ensures that any key resolved from a PyJWK context is forced through the same validation checks as a raw key, causing the library to throw an InvalidKeyError if the key length is zero.

The secondary patch acts as a defense-in-depth measure within the JWK parser in jwt/algorithms.py. When an HMAC key is loaded via the from_jwk interface, the updated logic validates the length of the decoded key material before creating the internal representation. If the decoded byte sequence is empty, the parser raises an InvalidKeyError during key initialization, preventing the creation of a vulnerable PyJWK instance entirely.

# Patched code in HMACAlgorithm.from_jwk (jwt/algorithms.py)
key_bytes = base64url_decode(obj["k"])
if len(key_bytes) == 0:
    raise InvalidKeyError("HMAC key must not be empty.")  # Prevent loading empty oct keys
return key_bytes

Exploitation Mechanics

Exploitation of CVE-2026-102266 requires specific environmental criteria but presents a low attack complexity once those criteria are met. The target application must process token signatures using keys retrieved from a JSON Web Key Set (JWKS). Crucially, the JWKS must contain an oct key with an empty key parameter "k": "". This condition often arises in testing environments, misconfigured directory services, or situations where keys are populated from uninitialized databases.

Once an empty oct key is present in the active JWKS, the attacker can execute the exploit completely offline. The attacker constructs a JWT payload with administrative privileges or desired claims, referencing the identifier (kid) of the empty key in the header. The attacker then generates an HMAC-SHA256 signature using a zero-length byte string (b"") as the secret key. The resulting base64url-encoded signature is appended to the token header and payload.

The following test script demonstrates how the signature generation is constructed and demonstrates how vulnerable versions of PyJWT accept the forged token, while patched versions throw an exception:

import base64
import hashlib
import hmac
import jwt
 
def test_exploit():
    empty_jwk = {
        "kty": "oct",
        "k": "",
        "kid": "active",
        "alg": "HS256"
    }
    jwk_obj = jwt.PyJWK.from_dict(empty_jwk)
    signing_input = b"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdHRhY2tlciJ9"
    signature_bytes = hmac.new(b"", signing_input, hashlib.sha256).digest()
    encoded_signature = base64.urlsafe_b64encode(signature_bytes).rstrip(b"=")
    token = (signing_input + b"." + encoded_signature).decode()
    
    try:
        decoded = jwt.decode(token, jwk_obj, algorithms=["HS256"])
        print("Verification Succeeded: " + str(decoded))
    except jwt.InvalidKeyError as e:
        print("Verification Blocked: " + str(e))

Impact Assessment

The impact of CVE-2026-102266 is high because it allows complete authentication and authorization bypass. An attacker who successfully exploits this vulnerability can forge valid cryptographic signatures representing any user identity, including administrative accounts. In typical deployments where JWTs are used to transmit authorization claims, this enables unauthorized privilege escalation, complete data access, and administrative control over the affected application.

The National Vulnerability Database assigns this vulnerability a CVSS score of 7.4. The vector string is CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N. The attack vector is Network, indicating remote exploitation capability. The complexity is High because of the prerequisite that the trust store contains an empty key. Confidentially and integrity impacts are both rated High, as arbitrary operations can be performed on behalf of simulated user sessions.

Although no active in-the-wild exploitation has been recorded by CISA or threat intelligence networks, the availability of clear proof-of-concept material increases the threat profile. Software developers and operations teams must prioritize remediation, particularly in multi-tenant environments where JWK Sets are dynamically fetched or managed by tenant-controlled identity providers.

Remediation and Mitigation

The primary remediation strategy is upgrading the PyJWT library to version 2.14.0 or higher. This version integrates the dual fixes that enforce strict key length validations on the PyJWK verification path and block empty HMAC keys during dynamic JWK parsing. The update is backwards-compatible and can be applied through python package managers using standard commands such as pip install --upgrade pyjwt.

When immediate upgrading is not feasible, several defensive workarounds can be applied at the application or gateway layer. Security teams should enforce key length validations by explicitly passing the enforce_minimum_key_length configuration option as True during token decoding. This ensures that even if an empty key bypasses the initial check, the signature validation phase raises an error due to the insufficient key length.

Additionally, applications that ingest remote JWK Sets should sanitize incoming keys. The sanitization logic must inspect the key list and explicitly reject any oct key where the k parameter is absent, null, or is an empty string. This preventative step blocks the entry of the vulnerable condition into the active key memory, mitigating the root cause of the signature bypass.

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.18%
Top 94% most exploited

Affected Systems

pyjwt (Python implementation of JSON Web Token)
AttributeDetail
CWE IDCWE-347
Attack VectorNetwork (AV:N)
CVSS7.4
EPSS0.00175
ImpactAuthentication Bypass / Privilege Escalation
Exploit StatusProof-of-Concept
KEV StatusNot Listed
CWE-347
Improper Verification of Cryptographic Signature

The software imports or uses a cryptographic key or signature but does not verify or improperly verifies the signature, allowing attackers to bypass authentication or integrity checks.

Vulnerability Timeline

PyJWT 2.13.0 is released, introducing modifications to the key processing/detached payload pathways.
2026-05-21
Initial vulnerability fix is developed and committed to the PyJWT repository.
2026-09-09
Defense-in-depth patch is committed to ensure from_jwk handles empty parameters securely.
2026-09-11
PyJWT version 2.14.0 is tagged and released, containing full resolutions for CVE-2026-102266.
2026-09-11
CVE-2026-102266 is officially published to the National Vulnerability Database.
2026-09-28

References & Sources

  • [1]NVD Reference
  • [2]CVE Record
  • [3]GitHub Advisory Database
  • [4]Official Release Notes

More Reports

•about 1 hour ago•GHSA-V53P-9FQP-M79J
7.5

GHSA-V53P-9FQP-M79J: Regular Expression Denial of Service (ReDoS) in Nodemailer addressparser

A Regular Expression Denial of Service (ReDoS) vulnerability exists in Nodemailer's addressparser fallback engine before version 10.0.6. Under specific malformed inputs with excessive word boundaries, the parser exhibits quadratic backtracking, leading to high CPU utilization and event loop blockage.

Amit Schendel
Amit Schendel
3 views•6 min read
•about 2 hours ago•GHSA-G57G-F23G-4646
6.5

GHSA-G57G-F23G-4646: Parser Differential and SMTP Injection in Nodemailer Address Parser

Nodemailer versions prior to 10.0.9 are vulnerable to a parser differential bug. When processing a quoted local-part followed by an RFC 5322 comment and trailing characters, the internal addressparser module fails to order its normalization routine correctly. This error results in the generation of malformed envelope recipient addresses containing injected whitespace and secondary domains, allowing attackers to bypass routing restrictions and exfiltrate sensitive emails.

Alon Barad
Alon Barad
4 views•7 min read
•about 3 hours ago•CVE-2026-102276
7.5

CVE-2026-102276: Denial of Service via Uncontrolled Recursion and Argument-List Exhaustion in brace-expansion

CVE-2026-102276 is a high-severity Denial of Service (DoS) vulnerability impacting the 'brace-expansion' library, a popular Node.js utility designed to expand brace patterns into combinatorial lists. Due to uncontrolled recursion and argument-list stack exhaustion within the internal parseCommaParts function, remote attackers can trigger an unhandled RangeError that abruptly terminates the Node.js process.

Alon Barad
Alon Barad
6 views•7 min read
•about 4 hours ago•CVE-2026-102278
7.5

CVE-2026-102278: Stack-Based Denial of Service via Uncontrolled Recursion in brace-expansion

A stack-based Denial of Service (DoS) vulnerability via uncontrolled recursion in the brace-expansion library prior to versions 1.1.20, 2.1.6, 3.0.8, and 5.0.11 allows unauthenticated remote attackers to trigger native stack exhaustion, terminating the Node.js process via a crafted payload containing deeply nested brace groups.

Amit Schendel
Amit Schendel
9 views•7 min read
•about 5 hours ago•CVE-2026-102277
5.3

CVE-2026-102277: Denial of Service via Quadratic Algorithmic Complexity in brace-expansion

An uncontrolled resource consumption vulnerability exists in the brace-expansion JavaScript library. Due to an algorithmic flaw in parsing a legacy Bash-compatibility quirk involving {a},b}-shaped expansion structures, untrusted inputs containing many trailing closing braces trigger successive full-input rescans. This behavior yields quadratic CPU time complexity and high memory overhead, allowing remote, unauthenticated attackers to cause a Denial of Service (DoS) by blocking the single-threaded Node.js event loop.

Amit Schendel
Amit Schendel
7 views•7 min read
•about 6 hours ago•CVE-2026-17495
5.9

CVE-2026-17495: Path Traversal via Type Confusion in Moment.js Dynamic Locale Loading

Moment.js versions 2.29.2 through 2.30.1 are vulnerable to a Path Traversal flaw (CWE-27) on server-side Node.js environments when dynamic locales are configured. The vulnerability stems from an object-coercion bypass in the locale-name sanitization routine, which assumes incoming variables are string primitives. An attacker can pass a structured object with custom 'match' and 'toString' properties to bypass regex-based directory checks, leading to arbitrary file loading via Node's internal 'require()' call.

Amit Schendel
Amit Schendel
5 views•6 min read