CVE-2026-101918: PyJWT Denial of Service Vulnerability

MODERATE
Advisory Identifier: GHSA-42vr-xj54-vc7v
CVSS 5.3
CWE-248
Published
Advisory Summary

CVE-2026-101918 is a MODERATE (CVSS 5.3) denial of service vulnerability (CWE-248: Uncaught Exception) affecting PyJWT libraries in the PyPI ecosystem. The issue involves unauthenticated recursionerror dos in pre-verification payload parse (pyjwkclient.get_signing_key_from_jwt / verify_signature=false). Remediation is available by upgrading affected packages to version 2.15.0.

CVE-2026-101918 at a Glance

CVE Identifier CVE-2026-101918
GHSA Identifier GHSA-42vr-xj54-vc7v
Severity MODERATE
CVSS v3.1 Base Score 5.3
CWE Classification CWE-248: Uncaught Exception
Affected Product PyJWT
Package Ecosystem PyPI
Published Date
Last Updated

Security Impact

CVSS: 5.3

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity None (I:N)
Availability Low (A:L)

How to Fix CVE-2026-101918

To remediate this vulnerability, upgrade all affected PyJWT dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

PyJWT fixed: 2.15.0
pip install PyJWT>=2.15.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

pip show PyJWT

How to Check if You Are Affected

To determine whether your Python environment is affected by CVE-2026-101918, inspect your installed packages using pip:

pip show PyJWT

Analyze the terminal output to locate any version of PyJWT in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2.15.0), your application is affected.

Note: The pip show PyJWT command checks currently installed packages in your active Python environment.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-248: Uncaught Exception, where an exception is thrown from a function, but it is not caught. In PyJWT, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## 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 unauthenticated attacker fully controls — was left catching `ValueError` alone, so that security fix does not fully hold. A second, related instance: `PyJWKClient.fetch_data` (`jwt/jwks_client.py:168`) parses a JWKS endpoint's response with `json.load(response)` inside a `try` that only catches `(URLError, TimeoutError, http.client.HTTPException)` — a deeply-nested JSON response from a JWKS endpoint raises the same raw `RecursionError`, uncaught entirely (worse than the payload path, which at least caught plain `ValueError`). **Affected versions:** confirmed present in the current release, 2.14.0, and on the current `master` branch (commit `4adcd02722f5011c60079d3978dfc167b9a8eaa5`). ## Reproduction ```python import base64, json, jwt def b64url(b): return base64.urlsafe_b64encode(b).rstrip(b"=") header = b64url(json.dumps({"alg": "HS256", "typ": "JWT"}).encode()) payload = b64url(b"[" * 20_000 + b"]" * 20_000) token = (header + b"." + payload + b"." + b64url(b"forged-sig")).decode() jwt.decode(token, options={"verify_signature": False}) # raises: RecursionError (not DecodeError/InvalidTokenError/PyJWTError) ``` Control: the same deeply-nested structure moved into the token's **header** instead of its payload is correctly converted to `jwt.DecodeError` by the already-hardened `jwt/api_jws.py:360` — confirming the payload path is specifically the missed half of the v2.14.0 hardening, not a general gap. ## Impact assessment Unauthenticated denial-of-service via unhandled exception on an auth path. Not an auth bypass — rated medium. With signature verification enabled, this parse runs after `_verify_signature`, so only the pre-verification paths (`get_signing_key_from_jwt`, explicit `verify_signature=False`) are attacker-reachable pre-auth; the JWKS-endpoint variant requires control of (or a MITM on) the configured JWKS endpoint rather than being reachable from an arbitrary client token. ## Suggested fix In `jwt/api_jwt.py:299`, change `except ValueError as e:` to `except (ValueError, RecursionError) as e:`, mirroring `jwt/api_jws.py:360` exactly. In `jwt/jwks_client.py`, add the same `(ValueError, RecursionError)` handling around `json.load(response)` in `fetch_data`, raising `PyJWKClientError` (consistent with the method's existing documented error contract). A patch implementing both, verified against the full test suite (457 passed, 4 skipped — pre-existing, environment-related) and against the reproduction above (now correctly raises `DecodeError`), is attached (`fix.patch`). ## Discovery method Found and verified using `scopegrep` (https://github.com/not-ekalabya/scopegrep) — a semantic code-retrieval tool that surfaces every other call site of a symbol alongside relevance-ranked results, which is what surfaced the already-hardened header path as the direct comparison here — paired with an LLM coding agent (GLM-5.3) run as an open-ended security review of this repository. Independently reproduced against the exact commit above before this report was written. Happy to share the full session transcript on request. ## Disclosure status Not shared with any other party or published. Submitting through this private channel per the project's stated security policy; no planned public/conference disclosure ahead of a coordinated timeline. --- ## Maintainer triage update (2026-09-22) ### Confirmed finding and scope We confirmed that an attacker-controlled recursively nested JWT payload can cause a raw Python `RecursionError` to escape PyJWT at PyJWT 2.14.0 and the tested current source. The confirmed in-scope paths are direct decoding with `verify_signature=False` and `PyJWKClient.get_signing_key_from_jwt`, where payload parsing occurs before key lookup. The demonstrated impact is limited to an uncaught exception for the affected call, which may surface as an application HTTP 500 when the application does not catch it. Testing did not demonstrate a worker or process crash, persistent resource exhaustion, resource amplification, authentication bypass, or confidentiality or integrity impact. The separate JWKS-response subclaim is out of scope under the policy boundary that requires the application to trust its configured JWKS source and transport. The confirmed payload finding is not a duplicate of the earlier protected-header parser finding: it occurs in a distinct payload parsing path that remained affected after the earlier header-only fix. ### Version and remediation status Historical testing reproduced the confirmed payload behavior in all 20 official supported PyJWT 2.x releases from 2.0.0a1 through 2.14.0, inclusive. Unsupported PyJWT 1.7.1 also reproduces the behavior, but it is excluded from the advisory range under the supported-2.x policy. No supported unaffected release and no patched release exists. The exact evidence is `/Users/jpadilla/.codex/security-advisories/pyjwt/GHSA-42vr-xj54-vc7v-historical-range-20260922.md` (SHA-256 `c48f1ac35641e9382d53e6a879a71ad9a8fb4432bbe871f2b8330f8d166a2d81`) and `/Users/jpadilla/.codex/security-advisories/pyjwt/historical-range-42vr-20260922/historical-range-results.json` (SHA-256 `324997f231561bf6da39b8f9d1e272f69bfde8871a7863f5cb7b70e22e91f076`). The evidence-backed supported affected range is `>= 2.0.0a1, <= 2.14.0`. Historical range verification is complete. A local fix commit exists and has passed independent review and the complete local CI suite, but it has not been merged into `master` or released. Consequently, `patched_versions` remains empty and this advisory remains in `triage`. The remaining next step is a maintainer decision on remediation and merge. After a fix lands in `master` and is released, `patched_versions` and advisory lifecycle can be updated in a separate approved batch. --- ## Maintainer remediation update (2026-09-23) The confirmed payload-parser finding has been fixed on `master`. Commit `5fde08a6cf906aa7698de2d6391d88b73006b17b` converts a recursive payload parse failure to the expected `DecodeError`; commit `9bc06658f875b9b40091539140bbbdc4639161c3` makes the regression tests deterministic across supported Python versions. This update supersedes the 2026-09-22 remediation-status statement that the fix had not landed. The original pre-verification payload reproducer and the `PyJWKClient.get_signing_key_from_jwt` path were covered by regression tests. The exact landed tree passed the full 39-environment local tox matrix and GitHub CI for commit `9bc06658f875b9b40091539140bbbdc4639161c3` passed all 25 jobs, including Ubuntu Python 3.14 and 3.15. The demonstrated impact remains an uncaught request-level exception in affected releases; there is still no evidence of process termination, persistent resource exhaustion, authentication bypass, or confidentiality or integrity impact. The supported affected range remains `>= 2.0.0a1, <= 2.14.0`. The latest released version is 2.14.0, which predates these commits; no released patched version exists yet, so `patched_versions` remains unset. CVSS v3.1 5.3 (Medium) and CWE-248 remain unchanged. The advisory may now move from triage to private draft. The next lifecycle step is a new supported 2.x release containing the fix, followed by separately approved patched-version and publication updates after release verification. --- ## Maintainer release update (2026-09-23) PyJWT 2.15.0 is the first released version containing the payload-parser fix. Its GitHub release tag points to commit `1d41a6478e1562e68ff667fcd703356acf085f68`, which includes fix commit `5fde08a6cf906aa7698de2d6391d88b73006b17b` and deterministic regression-test commit `9bc06658f875b9b40091539140bbbdc4639161c3`. PyPI published both the wheel and source distribution from that release commit through the successful production workflow at https://github.com/jpadilla/pyjwt/actions/runs/35891602963. The published PyPI wheel (`pyjwt-2.15.0-py3-none-any.whl`, SHA-256 `7a3742debf6b879e912dbb9819ceec1594be812452b78c5f2e2dfc56564954f8`) was checked directly: the deeply nested unsigned payload now raises `DecodeError`, while an ordinary unsigned payload still decodes. The supported affected range remains `>= 2.0.0a1, <= 2.14.0`; the patched version is `2.15.0`. Earlier statements in this advisory that no released patched version exists are superseded by this update. The confirmed impact remains an uncaught request-level exception in affected versions, not a demonstrated process crash or authentication bypass. The separate JWKS-response subclaim remains outside this advisory's confirmed PyJWT-owned scope.

CVE-2026-101918 Affected PyJWT Versions

1 component(s)
Fixed Versions:
2.15.0
Product / Package Ecosystem Affected Versions Fixed Version
PyJWT
PyPI
≥ 2.0.0a1
< 2.15.0
2.15.0

References

Frequently Asked Questions

What is CVE-2026-101918?
CVE-2026-101918 is a security vulnerability in PyJWT involving Unauthenticated RecursionError DoS in pre-verification payload parse (PyJWKClient.get_signing_key_from_jwt / verify_signature=False) under CWE-248: Uncaught Exception.
Which PyJWT versions are affected?
Affected versions include releases prior to 2.15.0 across affected packages: PyJWT.
What version fixes CVE-2026-101918?
Upgrading to 2.15.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is PyJWT affected?
Yes, PyJWT is affected in releases prior to 2.15.0. Upgrade your dependency to 2.15.0 or later.
What is the CVSS score of CVE-2026-101918?
CVE-2026-101918 has a CVSS v3.1 base score of 5.3 (MODERATE) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L.
What CWE is associated with CVE-2026-101918?
CVE-2026-101918 is classified under CWE-248: Uncaught Exception (An exception is thrown from a function, but it is not caught.).
How can I check PyPI dependencies for CVE-2026-101918?
Run the dependency tree command: 'pip show PyJWT'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-42vr-xj54-vc7v",
  "modified" : "2026-09-30T15:41:05Z",
  "published" : "2026-09-30T15:41:05Z",
  "aliases" : [ "CVE-2026-101918" ],
  "summary" : "PyJWT: Unauthenticated RecursionError DoS in pre-verification payload parse (PyJWKClient.get_signing_key_from_jwt / verify_signature=False)",
  "details" : "## Summary\n\n`PyJWKClient.get_signing_key_from_jwt(token)` — the first step of the JWKS\nverification flow documented in `docs/usage.rst` — must decode a token's\npayload before its signature can be checked, via\n`jwt.api_jwt.decode_complete(token, options={\"verify_signature\": False})`.\nThat call parses the payload with `json.loads` in `PyJWT._decode_payload`\n(`jwt/api_jwt.py:297-300`), whose `except` clause catches only `ValueError`.\nA payload that is valid JSON but nested ~20,000 levels deep makes\n`json.loads` raise `RecursionError`, which is **not** a `ValueError` and\nescapes as a raw, undocumented exception type — not `DecodeError`,\n`InvalidTokenError`, or `PyJWTError`, so every documented error-handling\npattern in `docs/usage.rst` misses it.\n\nThe token needs no valid signature and no network access — the crash\nhappens during payload parsing, before the `kid` is even looked up. A\nsingle unauthenticated ~50KB request crashes the caller's auth handler\n(HTTP 500 / dead worker), repeatably. The same path is reachable through\nplain `jwt.decode(token, options={\"verify_signature\": False})` too.\n\nNotably, this project already fixed the **identical** bug class for the\nJWS **header** path — `PyJWS._load` catches `(ValueError, RecursionError)`\nand wraps it in `DecodeError` (`jwt/api_jws.py:360-361`), and\n`CHANGELOG.rst` (v2.14.0, \"Security\") states \"Handle deeply nested and\nmalformed JWS/JWK input without uncaught recursion errors.\" The payload\npath — the one part of a forged token an unauthenticated attacker fully\ncontrols — was left catching `ValueError` alone, so that security fix does\nnot fully hold.\n\nA second, related instance: `PyJWKClient.fetch_data` (`jwt/jwks_client.py:168`)\nparses a JWKS endpoint's response with `json.load(response)` inside a\n`try` that only catches `(URLError, TimeoutError, http.client.HTTPException)`\n— a deeply-nested JSON response from a JWKS endpoint raises the same raw\n`RecursionError`, uncaught entirely (worse than the payload path, which at\nleast caught plain `ValueError`).\n\n**Affected versions:** confirmed present in the current release, 2.14.0,\nand on the current `master` branch (commit `4adcd02722f5011c60079d3978dfc167b9a8eaa5`).\n\n## Reproduction\n\n```python\nimport base64, json, jwt\n\ndef b64url(b):\n    return base64.urlsafe_b64encode(b).rstrip(b\"=\")\n\nheader = b64url(json.dumps({\"alg\": \"HS256\", \"typ\": \"JWT\"}).encode())\npayload = b64url(b\"[\" * 20_000 + b\"]\" * 20_000)\ntoken = (header + b\".\" + payload + b\".\" + b64url(b\"forged-sig\")).decode()\n\njwt.decode(token, options={\"verify_signature\": False})\n# raises: RecursionError (not DecodeError/InvalidTokenError/PyJWTError)\n```\n\nControl: the same deeply-nested structure moved into the token's **header**\ninstead of its payload is correctly converted to `jwt.DecodeError` by the\nalready-hardened `jwt/api_jws.py:360` — confirming the payload path is\nspecifically the missed half of the v2.14.0 hardening, not a general gap.\n\n## Impact assessment\n\nUnauthenticated denial-of-service via unhandled exception on an auth path.\nNot an auth bypass — rated medium. With signature verification enabled,\nthis parse runs after `_verify_signature`, so only the pre-verification\npaths (`get_signing_key_from_jwt`, explicit `verify_signature=False`) are\nattacker-reachable pre-auth; the JWKS-endpoint variant requires control of\n(or a MITM on) the configured JWKS endpoint rather than being reachable\nfrom an arbitrary client token.\n\n## Suggested fix\n\nIn `jwt/api_jwt.py:299`, change `except ValueError as e:` to\n`except (ValueError, RecursionError) as e:`, mirroring\n`jwt/api_jws.py:360` exactly. In `jwt/jwks_client.py`, add the same\n`(ValueError, RecursionError)` handling around `json.load(response)` in\n`fetch_data`, raising `PyJWKClientError` (consistent with the method's\nexisting documented error contract). A patch implementing both, verified\nagainst the full test suite (457 passed, 4 skipped — pre-existing,\nenvironment-related) and against the reproduction above (now correctly\nraises `DecodeError`), is attached (`fix.patch`).\n\n## Discovery method\n\nFound and verified using `scopegrep` (https://github.com/not-ekalabya/scopegrep)\n— a semantic code-retrieval tool that surfaces every other call site of a\nsymbol alongside relevance-ranked results, which is what surfaced the\nalready-hardened header path as the direct comparison here — paired with\nan LLM coding agent (GLM-5.3) run as an open-ended security review of this\nrepository. Independently reproduced against the exact commit above before\nthis report was written. Happy to share the full session transcript on\nrequest.\n\n## Disclosure status\n\nNot shared with any other party or published. Submitting through this\nprivate channel per the project's stated security policy; no planned\npublic/conference disclosure ahead of a coordinated timeline.\n\n\n---\n\n## Maintainer triage update (2026-09-22)\n\n### Confirmed finding and scope\n\nWe confirmed that an attacker-controlled recursively nested JWT payload can cause a raw Python `RecursionError` to escape PyJWT at PyJWT 2.14.0 and the tested current source. The confirmed in-scope paths are direct decoding with `verify_signature=False` and `PyJWKClient.get_signing_key_from_jwt`, where payload parsing occurs before key lookup.\n\nThe demonstrated impact is limited to an uncaught exception for the affected call, which may surface as an application HTTP 500 when the application does not catch it. Testing did not demonstrate a worker or process crash, persistent resource exhaustion, resource amplification, authentication bypass, or confidentiality or integrity impact.\n\nThe separate JWKS-response subclaim is out of scope under the policy boundary that requires the application to trust its configured JWKS source and transport. The confirmed payload finding is not a duplicate of the earlier protected-header parser finding: it occurs in a distinct payload parsing path that remained affected after the earlier header-only fix.\n\n### Version and remediation status\n\nHistorical testing reproduced the confirmed payload behavior in all 20 official supported PyJWT 2.x releases from 2.0.0a1 through 2.14.0, inclusive. Unsupported PyJWT 1.7.1 also reproduces the behavior, but it is excluded from the advisory range under the supported-2.x policy. No supported unaffected release and no patched release exists. The exact evidence is `/Users/jpadilla/.codex/security-advisories/pyjwt/GHSA-42vr-xj54-vc7v-historical-range-20260922.md` (SHA-256 `c48f1ac35641e9382d53e6a879a71ad9a8fb4432bbe871f2b8330f8d166a2d81`) and `/Users/jpadilla/.codex/security-advisories/pyjwt/historical-range-42vr-20260922/historical-range-results.json` (SHA-256 `324997f231561bf6da39b8f9d1e272f69bfde8871a7863f5cb7b70e22e91f076`). The evidence-backed supported affected range is `>= 2.0.0a1, <= 2.14.0`.\n\nHistorical range verification is complete. A local fix commit exists and has passed independent review and the complete local CI suite, but it has not been merged into `master` or released. Consequently, `patched_versions` remains empty and this advisory remains in `triage`. The remaining next step is a maintainer decision on remediation and merge. After a fix lands in `master` and is released, `patched_versions` and advisory lifecycle can be updated in a separate approved batch.\n\n---\n\n## Maintainer remediation update (2026-09-23)\n\nThe confirmed payload-parser finding has been fixed on `master`. Commit\n`5fde08a6cf906aa7698de2d6391d88b73006b17b` converts a recursive\npayload parse failure to the expected `DecodeError`; commit\n`9bc06658f875b9b40091539140bbbdc4639161c3` makes the regression tests\ndeterministic across supported Python versions. This update supersedes the\n2026-09-22 remediation-status statement that the fix had not landed.\n\nThe original pre-verification payload reproducer and the\n`PyJWKClient.get_signing_key_from_jwt` path were covered by regression tests.\nThe exact landed tree passed the full 39-environment local tox matrix and\nGitHub CI for commit `9bc06658f875b9b40091539140bbbdc4639161c3` passed\nall 25 jobs, including Ubuntu Python 3.14 and 3.15. The demonstrated impact\nremains an uncaught request-level exception in affected releases; there is\nstill no evidence of process termination, persistent resource exhaustion,\nauthentication bypass, or confidentiality or integrity impact.\n\nThe supported affected range remains `>= 2.0.0a1, <= 2.14.0`. The latest\nreleased version is 2.14.0, which predates these commits; no released\npatched version exists yet, so `patched_versions` remains unset. CVSS v3.1\n5.3 (Medium) and CWE-248 remain unchanged. The advisory may now move from\ntriage to private draft. The next lifecycle step is a new supported 2.x\nrelease containing the fix, followed by separately approved patched-version\nand publication updates after release verification.\n\n---\n\n## Maintainer release update (2026-09-23)\n\nPyJWT 2.15.0 is the first released version containing the payload-parser fix. Its GitHub release tag points to commit `1d41a6478e1562e68ff667fcd703356acf085f68`, which includes fix commit `5fde08a6cf906aa7698de2d6391d88b73006b17b` and deterministic regression-test commit `9bc06658f875b9b40091539140bbbdc4639161c3`. PyPI published both the wheel and source distribution from that release commit through the successful production workflow at https://github.com/jpadilla/pyjwt/actions/runs/35891602963.\n\nThe published PyPI wheel (`pyjwt-2.15.0-py3-none-any.whl`, SHA-256 `7a3742debf6b879e912dbb9819ceec1594be812452b78c5f2e2dfc56564954f8`) was checked directly: the deeply nested unsigned payload now raises `DecodeError`, while an ordinary unsigned payload still decodes. The supported affected range remains `>= 2.0.0a1, <= 2.14.0`; the patched version is `2.15.0`. Earlier statements in this advisory that no released patched version exists are superseded by this update.\n\nThe confirmed impact remains an uncaught request-level exception in affected versions, not a demonstrated process crash or authentication bypass. The separate JWKS-response subclaim remains outside this advisory's confirmed PyJWT-owned scope.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "PyJWT"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "2.0.0a1"
      }, {
        "fixed" : "2.15.0"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 2.14.0"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/jpadilla/pyjwt/security/advisories/GHSA-42vr-xj54-vc7v"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-101918"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/jpadilla/pyjwt/commit/5fde08a6cf906aa7698de2d6391d88b73006b17b"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/jpadilla/pyjwt"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/jpadilla/pyjwt/releases/tag/2.15.0"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-248" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-09-30T15:41:05Z",
    "nvd_published_at" : "2026-09-28T21:17:13Z"
  }
}