Skip to content

[Security] HIGH: RSA JWK parameter validation missing; MEDIUM: SHA-1 in RSA_OAEP; algorithms=None bypass #417

Description

@Nothern131

python-jose Security Vulnerability Report

Target: https://github.com/mpdavis/python-jose (v3.5.0)
Reporter: Nothern131 (AI-assisted automated security audit)
Date: 2026-08-16

Summary

Severity Vulnerability File Confirmed
HIGH RSA JWK parameter validation missing jose/backends/cryptography_backend.py Verified
MEDIUM RSA_OAEP uses deprecated SHA-1 jose/backends/cryptography_backend.py:209 Verified
MEDIUM algorithms=None skips algorithm check jose/jws.py:257 Verified
LOW Unrestricted JWS token size (DoS) jose/constants.py Verified

HIGH: RSA JWK Parameter Validation Missing (CVSS 7.5)

File: https://github.com/mpdavis/python-jose/blob/main/jose/backends/cryptography_backend.py

The CryptographyRSAKey._process_jwk() method accepts JWK dictionaries without validating key parameters:

def _process_jwk(self, jwk_dict):
    if not jwk_dict.get("kty") == "RSA":
        raise JWKError(...)
    e = base64_to_long(jwk_dict.get("e", 256))  # Default e=256 is invalid!
    n = base64_to_long(jwk_dict.get("n"))
    public = rsa.RSAPublicNumbers(e, n)
    # No validation of n bit length, e value, or weak key detection

Issues:

  1. No minimum modulus size checkn can be arbitrarily small (e.g., 512-bit), trivially factorable
  2. Invalid default exponente defaults to 256 when not provided (should be 65537)
  3. No weak key detection — Fermat factorization, small-exponent attacks not prevented
  4. No exponent validatione must satisfy gcd(e, φ(n)) = 1

Impact: An attacker who controls a JWK Set endpoint (or can inject JWKs through kid lookup) can provide weak RSA keys. Applications using these keys for JWT verification would be vulnerable to key recovery attacks.

Fix: Add key size validation (minimum 2048 bits) and exponent validation:

e = base64_to_long(jwk_dict.get("e", 65537))
n = base64_to_long(jwk_dict.get("n"))
if n.bit_length() < 2048:
    raise JWKError("RSA modulus too small")
if e < 3 or e % 2 == 0:
    raise JWKError("Invalid RSA exponent")
public = rsa.RSAPublicNumbers(e, n)

MEDIUM: RSA_OAEP Uses SHA-1 (CVSS 5.3)

File: https://github.com/mpdavis/python-jose/blob/main/jose/backends/cryptography_backend.py#L209

RSA_OAEP = padding.OAEP(padding.MGF1(hashes.SHA1()), hashes.SHA1(), None)

SHA-1 is cryptographically broken (collisions demonstrated since 2017). RSA-OAEP is deprecated in favor of RSA-OAEP-256. This definition still exists and could be used if an application explicitly requests it.

Fix: Deprecate or remove RSA_OAEP (SHA-1), or add a deprecation warning.


MEDIUM: algorithms=None Skips Algorithm Check (CVSS 5.0)

File: https://github.com/mpdavis/python-jose/blob/main/jose/jws.py#L257

def _verify_signature(signing_input, header, signature, key="", algorithms=None):
    alg = header.get("alg")
    if not alg:
        raise JWSError("No algorithm was specified in the JWS header.")
    if algorithms is not None and alg not in algorithms:  # Skipped when algorithms=None
        raise JWSError("The specified alg value is not allowed")

When algorithms=None (the default in jwt.decode()), the algorithm whitelist check is completely bypassed. While the current code prevents alg=none by excluding it from SUPPORTED, this is a design flaw — it relies on the algorithm list being exhaustive rather than enforcing positive restrictions.

Fix: Require algorithms to be a non-None iterable:

if algorithms is None:
    raise JWSError("algorithms parameter is required")
if alg not in algorithms:
    raise JWSError("The specified alg value is not allowed")

LOW: Unrestricted JWS Token Size (CVSS 3.7)

File: https://github.com/mpdavis/python-jose/blob/main/jose/constants.py

JWE_SIZE_LIMIT = 250 * 1024 (250KB) exists but there is no equivalent limit for JWS tokens. A maliciously large JWT could cause memory exhaustion.

Fix: Add JWS_SIZE_LIMIT and enforce it during parsing.


Generated by AI Bug Bounty automated hunting tool:Reporter: Nothern131

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions