VYPR
Critical severityNVD Advisory· Published Nov 18, 2025· Updated Nov 19, 2025

joserfc has Possible Uncontrolled Resource Consumption Vulnerability Triggered by Logging Arbitrarily Large JWT Token Payloads

CVE-2025-65015

Description

joserfc is a Python library that provides an implementation of several JSON Object Signing and Encryption (JOSE) standards. In versions from 1.3.3 to before 1.3.5 and from 1.4.0 to before 1.4.2, the ExceededSizeError exception messages are embedded with non-decoded JWT token parts and may cause Python logging to record an arbitrarily large, forged JWT payload. In situations where a misconfigured — or entirely absent — production-grade web server sits in front of a Python web application, an attacker may be able to send arbitrarily large bearer tokens in the HTTP request headers. When this occurs, Python logging or diagnostic tools (e.g., Sentry) may end up processing extremely large log messages containing the full JWT header during the joserfc.jwt.decode() operation. The same behavior also appears when validating claims and signature payload sizes, as the library raises joserfc.errors.ExceededSizeError() with the full payload embedded in the exception message. Since the payload is already fully loaded into memory at this stage, the library cannot prevent or reject it. This issue has been patched in versions 1.3.5 and 1.4.2.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In joserfc library embeds raw JWT payloads in ExceededSizeError exceptions, which can cause uncontrolled resource consumption when logged.

Vulnerability

Overview

In joserfc versions 1.3.3 to before 1.3.5 and 1.4.0 to before 1.4.2, the ExceededSizeError exception messages include the raw, non-decoded JWT token parts (header, payload, or signature) that triggered the size check [1]. This means that when a JWT exceeds configured size limits, the library raises an exception whose message contains the full oversized token data.

Attack

Vector

An attacker can send an arbitrarily large bearer token in an HTTP request header to a Python web application that uses joserfc for JWT decoding [1]. If the application does not have a production-grade reverse proxy (e.g., nginx) or proper header size limits enforced by the web server (e.g., uvicorn/h11), the oversized JWT reaches the Python application. During joserfc.jwt.decode(), the library loads the entire payload into memory and then raises ExceededSizeError with the full payload embedded in the exception message [1].

Impact

When the exception is logged by Python logging frameworks or forwarded to diagnostic tools like Sentry, the extremely large log message can cause uncontrolled resource consumption (CPU, memory, disk I/O) [1]. This can lead to denial of service, as the logging system may become overwhelmed processing the oversized message. The library cannot prevent this because the payload is already fully loaded into memory before the size check occurs [1].

Mitigation

The issue has been patched in joserfc versions 1.3.5 and 1.4.2 [1]. The fix removes the raw value from the ExceededSizeError exception message, as shown in the commit diffs [3][4]. Users should update to the patched versions and also ensure that a reverse proxy or web server enforces appropriate header size limits to prevent oversized tokens from reaching the application [1].

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
joserfcPyPI
>= 1.3.3, < 1.3.51.3.5
joserfcPyPI
>= 1.4.0, < 1.4.21.4.2

Affected products

2
  • joserfc/joserfcllm-fuzzy
    Range: >=1.3.3, <1.3.5; >=1.4.0, <1.4.2
  • authlib/joserfcv5
    Range: >= 1.3.3, < 1.3.5

Patches

2
63932f169d92

fix: remove raw value from ExceededSizeError

https://github.com/authlib/joserfcHsiaoming YangNov 17, 2025via ghsa
2 files changed · +8 8
  • src/joserfc/_rfc7515/registry.py+3 3 modified
    @@ -101,15 +101,15 @@ def check_header(self, header: Header) -> None:
     
         def validate_header_size(self, header: bytes) -> None:
             if header and len(header) > self.max_header_length:
    -            raise ExceededSizeError(f"Header size of '{header!r}' exceeds {self.max_header_length} bytes.")
    +            raise ExceededSizeError(f"Header size exceeds {self.max_header_length} bytes.")
     
         def validate_payload_size(self, payload: bytes) -> None:
             if payload and len(payload) > self.max_payload_length:
    -            raise ExceededSizeError(f"Payload size of '{payload!r}' exceeds {self.max_payload_length} bytes.")
    +            raise ExceededSizeError(f"Payload size exceeds {self.max_payload_length} bytes.")
     
         def validate_signature_size(self, signature: bytes) -> None:
             if len(signature) > self.max_signature_length:
    -            raise ExceededSizeError(f"Signature of '{signature!r}' exceeds {self.max_signature_length} bytes.")
    +            raise ExceededSizeError(f"Signature of exceeds {self.max_signature_length} bytes.")
     
         @classmethod
         def guess_alg(cls, key: Any, strategy: Strategy) -> str | None:
    
  • src/joserfc/_rfc7516/registry.py+5 5 modified
    @@ -102,25 +102,25 @@ def check_header(self, header: Header, check_more: bool = False) -> None:
     
         def validate_protected_header_size(self, header: bytes) -> None:
             if header and len(header) > self.max_protected_header_length:
    -            raise ExceededSizeError(f"Header size of '{header!r}' exceeds {self.max_protected_header_length} bytes.")
    +            raise ExceededSizeError(f"Header size exceeds {self.max_protected_header_length} bytes.")
     
         def validate_encrypted_key_size(self, ek: bytes) -> None:
             if ek and len(ek) > self.max_encrypted_key_length:
    -            raise ExceededSizeError(f"Encrypted key size of '{ek!r}' exceeds {self.max_encrypted_key_length} bytes.")
    +            raise ExceededSizeError(f"Encrypted key size exceeds {self.max_encrypted_key_length} bytes.")
     
         def validate_initialization_vector_size(self, iv: bytes) -> None:
             if iv and len(iv) > self.max_initialization_vector_length:
                 raise ExceededSizeError(
    -                f"Initialization vector size of '{iv!r}' exceeds {self.max_initialization_vector_length} bytes."
    +                f"Initialization vector size exceeds {self.max_initialization_vector_length} bytes."
                 )
     
         def validate_ciphertext_size(self, ciphertext: bytes) -> None:
             if ciphertext and len(ciphertext) > self.max_ciphertext_length:
    -            raise ExceededSizeError(f"Ciphertext size of '{ciphertext!r}' exceeds {self.max_ciphertext_length} bytes.")
    +            raise ExceededSizeError(f"Ciphertext size exceeds {self.max_ciphertext_length} bytes.")
     
         def validate_auth_tag_size(self, tag: bytes) -> None:
             if tag and len(tag) > self.max_auth_tag_length:
    -            raise ExceededSizeError(f"Auth tag size of '{tag!r}' exceeds {self.max_auth_tag_length} bytes.")
    +            raise ExceededSizeError(f"Auth tag size exceeds {self.max_auth_tag_length} bytes.")
     
         def get_alg(self, name: str) -> JWEAlgModel:
             """Get the allowed ("alg") algorithm instance of the given name.
    
673c8743fd06

fix: remove raw value from ExceededSizeError

https://github.com/authlib/joserfcHsiaoming YangNov 17, 2025via ghsa
2 files changed · +8 8
  • src/joserfc/_rfc7515/registry.py+3 3 modified
    @@ -101,15 +101,15 @@ def check_header(self, header: Header) -> None:
     
         def validate_header_size(self, header: bytes) -> None:
             if header and len(header) > self.max_header_length:
    -            raise ExceededSizeError(f"Header size of '{header!r}' exceeds {self.max_header_length} bytes.")
    +            raise ExceededSizeError(f"Header size exceeds {self.max_header_length} bytes.")
     
         def validate_payload_size(self, payload: bytes) -> None:
             if payload and len(payload) > self.max_payload_length:
    -            raise ExceededSizeError(f"Payload size of '{payload!r}' exceeds {self.max_payload_length} bytes.")
    +            raise ExceededSizeError(f"Payload size exceeds {self.max_payload_length} bytes.")
     
         def validate_signature_size(self, signature: bytes) -> None:
             if len(signature) > self.max_signature_length:
    -            raise ExceededSizeError(f"Signature of '{signature!r}' exceeds {self.max_signature_length} bytes.")
    +            raise ExceededSizeError(f"Signature of exceeds {self.max_signature_length} bytes.")
     
         @classmethod
         def guess_alg(cls, key: Any, strategy: Strategy) -> str | None:
    
  • src/joserfc/_rfc7516/registry.py+5 5 modified
    @@ -102,25 +102,25 @@ def check_header(self, header: Header, check_more: bool = False) -> None:
     
         def validate_protected_header_size(self, header: bytes) -> None:
             if header and len(header) > self.max_protected_header_length:
    -            raise ExceededSizeError(f"Header size of '{header!r}' exceeds {self.max_protected_header_length} bytes.")
    +            raise ExceededSizeError(f"Header size exceeds {self.max_protected_header_length} bytes.")
     
         def validate_encrypted_key_size(self, ek: bytes) -> None:
             if ek and len(ek) > self.max_encrypted_key_length:
    -            raise ExceededSizeError(f"Encrypted key size of '{ek!r}' exceeds {self.max_encrypted_key_length} bytes.")
    +            raise ExceededSizeError(f"Encrypted key size exceeds {self.max_encrypted_key_length} bytes.")
     
         def validate_initialization_vector_size(self, iv: bytes) -> None:
             if iv and len(iv) > self.max_initialization_vector_length:
                 raise ExceededSizeError(
    -                f"Initialization vector size of '{iv!r}' exceeds {self.max_initialization_vector_length} bytes."
    +                f"Initialization vector size exceeds {self.max_initialization_vector_length} bytes."
                 )
     
         def validate_ciphertext_size(self, ciphertext: bytes) -> None:
             if ciphertext and len(ciphertext) > self.max_ciphertext_length:
    -            raise ExceededSizeError(f"Ciphertext size of '{ciphertext!r}' exceeds {self.max_ciphertext_length} bytes.")
    +            raise ExceededSizeError(f"Ciphertext size exceeds {self.max_ciphertext_length} bytes.")
     
         def validate_auth_tag_size(self, tag: bytes) -> None:
             if tag and len(tag) > self.max_auth_tag_length:
    -            raise ExceededSizeError(f"Auth tag size of '{tag!r}' exceeds {self.max_auth_tag_length} bytes.")
    +            raise ExceededSizeError(f"Auth tag size exceeds {self.max_auth_tag_length} bytes.")
     
         def get_alg(self, name: str) -> JWEAlgModel:
             """Get the allowed ("alg") algorithm instance of the given name.
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.