Skip to content
Heist/ feed
MediumFix available

PyJWT: Unauthenticated RecursionError DoS in pre-verification payload parse (PyJWKClient.get_signing_key_from_jwt / verify_signature=False)

Type: advisorySource: OSV2 source records

## Summary `PyJWKClient.get_signing_key_from_jwt(token)` — the first step of the JWKS verification flow documented in `docs/usage.rst` — must decode a token's payload before its signature can be checked, via `jwt.api_jwt.decode_complete(token, options={"verify_signature": False})`. That call parses the payload with `json.loads` in `PyJWT._decode_payload` (`jwt/api_jwt.py:297-300`), whose `except` clause catches only `ValueError`. A payload that is valid JSON but nested ~20,000 levels deep makes `json.loads` raise `RecursionError`, which is **not** a `ValueError` and escapes as a raw, undocumented exception type — not `DecodeError`, `InvalidTokenError`, or `PyJWTError`, so every documented error-handling pattern in `docs/usage.rst` misses it. The token needs no valid signature and no network access — the crash happens during payload parsing, before the `kid` is even looked up. A single unauthenticated ~50KB request crashes the caller's auth handler (HTTP 500 / dead worker), repeatably. The same path is reachable through plain `jwt.decode(token, options={"verify_signature": False})` too. Notably, this project already fixed the **identical** bug class for the JWS **header** path — `PyJWS._load` catches `(ValueError, RecursionError)` and wraps it in `DecodeError` (`jwt/api_jws.py:360-361`), and `CHANGELOG.rst` (v2.14.0, "Security") states "Handle deeply nested and malformed JWS/JWK input without uncaught recursion errors." The payload path — the one part of a forged token an unau

Announced Group revision 1
Original source ↗

PYSEC-2026-4141

Revision 1

PyJWT: Unauthenticated RecursionError DoS in pre-verification payload parse (PyJWKClient.get_signing_key_from_jwt / verify_signature=False)

## Summary `PyJWKClient.get_signing_key_from_jwt(token)` — the first step of the JWKS verification flow documented in `docs/usage.rst` — must decode a token's payload before its signature can be checked, via `jwt.api_jwt.decode_complete(token, options={"verify_signature": False})`. That call parses the payload with `json.loads` in `PyJWT._decode_payload` (`jwt/api_jwt.py:297-300`), whose `except` clause catches only `ValueError`. A payload that is valid JSON but nested ~20,000 levels deep makes `json.loads` raise `RecursionError`, which is **not** a `ValueError` and escapes as a raw, undocumented exception type — not `DecodeError`, `InvalidTokenError`, or `PyJWTError`, so every documented error-handling pattern in `docs/usage.rst` misses it. The token needs no valid signature and no network access — the crash happens during payload parsing, before the `kid` is even looked up. A single unauthenticated ~50KB request crashes the caller's auth handler (HTTP 500 / dead worker), repeatably. The same path is reachable through plain `jwt.decode(token, options={"verify_signature": False})` too. Notably, this project already fixed the **identical** bug class for the JWS **header** path — `PyJWS._load` catches `(ValueError, RecursionError)` and wraps it in `DecodeError` (`jwt/api_jws.py:360-361`), and `CHANGELOG.rst` (v2.14.0, "Security") states "Handle deeply nested and malformed JWS/JWK input without uncaught recursion errors." The payload path — the one part of a forged token an unau

Imported from structured advisory data. Source references identify upstream records or fields; verify affected versions and your deployed configuration.

Security context

Source reference: osv:PYSEC-2026-4141

pyjwt

Source reference: /affected/0/package/name

Affected versions
2.0.0

Source reference: /affected/0/versions

2.0.0a1

Source reference: /affected/0/versions

2.0.0a2

Source reference: /affected/0/versions

2.0.1

Source reference: /affected/0/versions

2.1.0

Source reference: /affected/0/versions

2.10.0

Source reference: /affected/0/versions

2.10.1

Source reference: /affected/0/versions

2.11.0

Source reference: /affected/0/versions

2.12.0

Source reference: /affected/0/versions

2.12.1

Source reference: /affected/0/versions

2.13.0

Source reference: /affected/0/versions

2.14.0

Source reference: /affected/0/versions

2.2.0

Source reference: /affected/0/versions

2.3.0

Source reference: /affected/0/versions

2.4.0

Source reference: /affected/0/versions

2.5.0

Source reference: /affected/0/versions

2.6.0

Source reference: /affected/0/versions

2.7.0

Source reference: /affected/0/versions

2.8.0

Source reference: /affected/0/versions

2.9.0

Source reference: /affected/0/versions

Fixed versions
2.15.0

Source reference: /affected/0/ranges

Prerequisites
Not stated in this record

Structured affected-version data

Original package identities and version rules from this source.

[
  {
    "ranges": [
      {
        "type": "ECOSYSTEM",
        "events": [
          {
            "introduced": "2.0.0a1"
          },
          {
            "fixed": "2.15.0"
          }
        ]
      }
    ],
    "package": {
      "name": "pyjwt",
      "purl": "pkg:pypi/pyjwt",
      "ecosystem": "PyPI"
    },
    "versions": [
      "2.0.0",
      "2.0.0a1",
      "2.0.0a2",
      "2.0.1",
      "2.1.0",
      "2.10.0",
      "2.10.1",
      "2.11.0",
      "2.12.0",
      "2.12.1",
      "2.13.0",
      "2.14.0",
      "2.2.0",
      "2.3.0",
      "2.4.0",
      "2.5.0",
      "2.6.0",
      "2.7.0",
      "2.8.0",
      "2.9.0"
    ],
    "database_specific": {
      "source": "https://github.com/pypa/advisory-database/blob/main/vulns/pyjwt/PYSEC-2026-4141.yaml"
    }
  }
]
Related CVEs
CVE-2026-101918

Source reference: /aliases

Publisher severity

No explicit severity was provided.

Linked CVE context

These ratings describe the referenced vulnerabilities and products. They are not a severity rating for every application using this dependency.

Event
#62512 · Revision 1
Added to Heist Feed
Publisher date
Read the original announcement

GHSA-42vr-xj54-vc7v

Primary source · Revision 1

Imported from structured advisory data. Source references identify upstream records or fields; verify affected versions and your deployed configuration.

Security context

Source reference: osv:GHSA-42vr-xj54-vc7v

pyjwt

Source reference: /affected/0/package/name

Affected versions
2.0.0

Source reference: /affected/0/versions

2.0.0a1

Source reference: /affected/0/versions

2.0.0a2

Source reference: /affected/0/versions

2.0.1

Source reference: /affected/0/versions

2.1.0

Source reference: /affected/0/versions

2.10.0

Source reference: /affected/0/versions

2.10.1

Source reference: /affected/0/versions

2.11.0

Source reference: /affected/0/versions

2.12.0

Source reference: /affected/0/versions

2.12.1

Source reference: /affected/0/versions

2.13.0

Source reference: /affected/0/versions

2.14.0

Source reference: /affected/0/versions

2.2.0

Source reference: /affected/0/versions

2.3.0

Source reference: /affected/0/versions

2.4.0

Source reference: /affected/0/versions

2.5.0

Source reference: /affected/0/versions

2.6.0

Source reference: /affected/0/versions

2.7.0

Source reference: /affected/0/versions

2.8.0

Source reference: /affected/0/versions

2.9.0

Source reference: /affected/0/versions

Fixed versions
2.15.0

Source reference: /affected/0/ranges

Prerequisites
Not stated in this record

Structured affected-version data

Original package identities and version rules from this source.

[
  {
    "ranges": [
      {
        "type": "ECOSYSTEM",
        "events": [
          {
            "introduced": "2.0.0a1"
          },
          {
            "fixed": "2.15.0"
          }
        ]
      }
    ],
    "package": {
      "name": "pyjwt",
      "purl": "pkg:pypi/pyjwt",
      "ecosystem": "PyPI"
    },
    "versions": [
      "2.0.0",
      "2.0.0a1",
      "2.0.0a2",
      "2.0.1",
      "2.1.0",
      "2.10.0",
      "2.10.1",
      "2.11.0",
      "2.12.0",
      "2.12.1",
      "2.13.0",
      "2.14.0",
      "2.2.0",
      "2.3.0",
      "2.4.0",
      "2.5.0",
      "2.6.0",
      "2.7.0",
      "2.8.0",
      "2.9.0"
    ],
    "database_specific": {
      "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/09/GHSA-42vr-xj54-vc7v/GHSA-42vr-xj54-vc7v.json",
      "last_known_affected_version_range": "<= 2.14.0"
    }
  }
]
Related CVEs
CVE-2026-101918

Source reference: /aliases

Publisher severity

No explicit severity was provided.

Linked CVE context

These ratings describe the referenced vulnerabilities and products. They are not a severity rating for every application using this dependency.

Event
#62573 · Revision 1
Added to Heist Feed
Publisher date
Read the original announcement