Skip to main content

PyJWT CVE-2026-102270

| EUVDEUVD-2026-88537 MEDIUM
Inefficient Regular Expression Complexity (ReDoS) (CWE-1333)
2026-09-28 GitHub_M GHSA-jwrc-g2q2-pq5p
4.9
CVSS 3.1 · NVD
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Gain control over key-input path (PR:H)
  2. Exploit
    Submit crafted PEM-like blob with repeated BEGIN, no END
  3. Execution
    is_pem_format regex backtracks unboundedly
  4. Impact
    CPU exhaustion / service DoS

Vulnerability Assessment

Weakness
CWE
ASVS 5.0
V2 - Validation and Business Logic Regex complexity limits
MITRE ATT&CK

1 technique across 1 tactic: Impact

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

Exploitation requires that the attacker control the key/secret material passed into PyJWT's key-preparation path (is_pem_format is invoked when checking whether a supplied key is PEM-formatted). The concrete trigger is a certificate-like input containing repeated '-----BEGIN <label>-----' markers with NO matching END marker, causing the pre-fix lazy regex ('.+?' under re.DOTALL) to backtrack without bound. Limiting factors: PR:H - key material is normally operator/config-controlled, so the vulnerable input is not reachable from unauthenticated request data in typical deployments; AC:H - the input must be specifically crafted to maximize backtracking; affects only PyJWT versions prior to 2.14.0. Impact is availability-only (CPU exhaustion); no data exposure or forgery.

Impact

This is a genuine but low-priority issue. The vendor CVSS 3.1 vector (AV:N/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:H, base 4.4) is internally consistent with a ReDoS: no confidentiality or integrity impact, availability-only, high attack complexity (crafting an input with repeated BEGIN markers and no matching END to force catastrophic backtracking), and high privileges required. The PR:H is the key signal - is_pem_format runs against the key/secret material handed to PyJWT, which in almost all deployments is operator-controlled configuration rather than untrusted request data, so an attacker generally needs privileged control over the key input to reach the vulnerable regex. No EPSS score, no CISA KEV listing, and no public exploit code are present in the input, so exploitation status is 'no public exploit identified at time of analysis.' The signals do not conflict: everything points to a narrow, low-real-risk CPU-exhaustion DoS in an extremely popular library. The ubiquitous deployment of PyJWT does NOT translate to wide exploitability here, because the trigger requires attacker influence over key material - a condition uncommon in typical architectures.

Exploit ScenarioDerived

In an application that passes externally-influenced key material into a PyJWT verification/signing path (e.g., a multi-tenant service where users supply their own signing keys or PEM certificates), an attacker submits a crafted certificate-like blob containing many repeated '-----BEGIN PUBLIC KEY-----' markers with no matching END marker. is_pem_format's lazy PEM regex backtracks unboundedly searching for the end marker, pinning a CPU core and degrading or stalling the service. No public POC is identified; the fix commit ships regression tests demonstrating the pathological input (10,000x repeated BEGIN).

This Month Plan within 30 days. Why: MEDIUM severity (CVSS 4.0-6.9).
Patch available 0.2% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Sep 28, 2026

CPU-exhaustion denial of service in PyJWT versions prior to 2.14.0, where the lazy PEM-detection regular expression used by is_pem_format() backtracks without bound on certificate-like input containing repeated '-----BEGIN <label>-----' markers and no matching END marker. The flaw is reachable only through the key-preparation path (the key/secret material supplied to PyJWT for verification/signing), which in normal deployments is operator- or configuration-controlled; the assessed vector accordingly requires high privileges (PR:H) and a specifically crafted input (AC:H), and impact is limited to availability with no confidentiality or integrity effect. No public exploit code has been identified at time of analysis and the issue is not confirmed actively exploited (CISA KEV), but a vendor fix exists and the issue was publicly disclosed, so unpatched instances should be upgraded promptly given the trivial resource-consumption nature of ReDoS bugs once a trigger is known.

RemediationAI

Upgrade PyJWT to version 2.14.0, the release that contains the fix (pip install --upgrade 'PyJWT>=2.14.0'); the same change is visible in commit 8b4e233a22206b34ec1186e912e75c0b2396ac07 and is documented in the GitHub advisory GHSA-jwrc-g2q2-pq5p (https://github.com/jpadilla/pyjwt/security/advisories/GHSA-jwrc-g2q2-pq5p) and the 2.14.0 release notes (https://github.com/jpadilla/pyjwt/releases/tag/2.14.0), so vendor-released patch 2.14.0 should be the target for every deployment. If an immediate upgrade is not possible, the most effective compensating control is to stop feeding attacker-influenced bytes into PyJWT's key argument: ensure keys and secrets are loaded exclusively from trusted configuration, files, or a managed key store rather than from request bodies, JWK headers, or user-supplied 'kid' lookups, since PR:H reflects that key material is normally operator-controlled - this removes the trigger entirely but may break features that deliberately accept caller-supplied keys. As a secondary control, enforce a strict maximum length (a few KB is far more than any legitimate PEM blob or HMAC secret needs) and reject keys containing multiple '-----BEGIN' markers before they reach prepare_key(), which bounds the backtracking work at the cost of rejecting unusual-but-valid inputs; also wrap JWT parsing in per-request CPU/time limits or isolate it in workers with concurrency caps, and monitor for CPU spikes or slow requests on endpoints that pass untrusted key material. Note that the fix also tightens accepted PEM mutations, so callers relying on malformed PEM (missing newlines, tabs before END, or trailing PEM blocks) being treated as non-PEM may see behavior changes after upgrading; validate against the upstream test expectations before rolling out.

Affected VersionsENISA

pyjwt < 2.14.0

Affected Packages

pypi pyjwt fix: 2.14.0

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in pypi

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

PyJWT is a Python implementation of the JWT/JWS/JWE standards, and before the fix its jwt/utils.py module used a single compiled regular expression (_PEM_RE) to decide whether a supplied key looked like PEM-encoded key material. That pattern combined a capture group around the allowed PEM labels with a non-greedy '.+?' body under re.DOTALL and a backreference (\1) to the matching END label. Because the body was lazy and the terminator required a backreferenced match that never appeared, the engine had to explore essentially every possible body length and every candidate END position for each BEGIN marker - classic catastrophic backtracking (CWE-1333, inefficient regular expression complexity). An input consisting of many repeated BEGIN markers with no END marker therefore produces runtime growth that is super-linear in input length, consuming CPU until the request or worker finishes. The upstream commit 8b4e233a22206b34ec1186e912e75c0b2396ac07 replaces the backtracking pattern with a zero-width lookahead marker scanner that records BEGIN labels and returns True only when a later matching END marker is found for the same label, making the check linear; the accompanying tests additionally confirm that incomplete marker sequences (e.g., b'-----BEGIN PUBLIC KEY-----' repeated 10,000 times) are accepted as non-PEM rather than triggering heavy matching. The CPE entry cpe:2.3:a:jpadilla:pyjwt:*:*:*:*:*:*:*:* identifies the jpadilla/pyjwt Python package across all releases prior to 2.14.0 as the affected component; the bug is purely algorithmic, so any deployment that routes attacker-influenced bytes into the key argument is exposed regardless of platform.

Know when Pyjwt gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (GitHub_M) PRIMARY MEDIUM
NVD 4.9 MEDIUM
AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H
vuln.today AI 4.4 MEDIUM

Key material is operator-controlled so PR:H; crafting a maximally-backtracking input is non-trivial so AC:H; impact is pure CPU-exhaustion DoS, hence A:H with C:N/I:N.

3.1 AV:N/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:H
4.0 AV:N/AC:H/AT:N/PR:H/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
SUSE 4.4 MEDIUM
AV:N/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:H
Red Hat 4.4 MEDIUM

Primary rating from Vendor (GitHub_M).

CVSS VectorNVD

Attack Vector
Network
Attack Complexity
Low
Privileges Required
High
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Lifecycle Timeline

3
CVSS changed
Oct 06, 2026 - 18:52 NVD
4.4 (MEDIUM) 4.9 (MEDIUM)
Patch available
Sep 28, 2026 - 22:02 EUVD
CVE Published
Sep 28, 2026 - 20:29 cve.org
MEDIUM 4.4

DescriptionNVD

PyJWT is a Python implementation of JSON Web Token standards. Prior to 2.14.0, PyJWT is_pem_format is affected because lazy PEM regular expression backtracks extensively. This occurs when a certificate-like input contains repeated BEGIN markers without a matching END marker. As a result, is_pem_format performs unbounded backtracking while searching for a PEM end marker. Consequently, an attacker can cause intensive CPU consumption. This issue is fixed in version 2.14.0.

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 17 pypi packages depend on pyjwt (16 direct, 1 indirect)

Ecosystem-wide dependent count for version 2.14.0.

Threat Intelligence Overview

EPSS Score
0.2%
Top 92% exploitable
Prevalence
Ubiquitous
PyJWT is the de facto standard Python JWT library, embedded in vast numbers of apps
Threat Intel
1
1 sources
Data Quality
7 sources
Confidence: High

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity MEDIUM
CISA KEV No
Public POC No
EPSS 0.2%
Patch available Yes
Active threat No
Deciding rule
MEDIUM severity (CVSS 4.0-6.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation
Poc
System Exposure· derived
Open
Automatable
No
Human Impact· derived
High
Technical Impact
Partial

Priority Score

24
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +24
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Denial of Service attacks render applications or systems unavailable by overwhelming resources or triggering failure conditions.

More in Pyjwt

View all
CVE-2026-102266 CRITICAL POC
9.1 Sep 28

Forged HS256 JSON Web Tokens can be accepted as authentic by PyJWT (pip package PyJWT) versions 2.13.0 through 2.13.x wh

CVE-2026-102275 HIGH POC
8.2 Sep 28

Improper validation in PyJWT 2.1.0 through 2.14.0 allows an attacker who already holds a stolen sender-constrained (DPoP

CVE-2026-102274 HIGH POC
7.5 Sep 28

Denial of service in PyJWT 2.9.0 through 2.13.0: a single malformed RSA JWK embedded in a JWK Set aborts construction of

CVE-2026-101918 HIGH POC
7.5 Sep 28

Unauthenticated denial of service in the PyJWT Python library (versions 2.0.0a1 through 2.14.0) allows a remote attacker

CVE-2024-53861 HIGH POC
7.5 Nov 29

pyjwt is a JSON Web Token implementation in Python. Rated high severity (CVSS 7.5), this vulnerability is remotely explo

CVE-2026-48526 HIGH POC
7.4 May 28

Authentication bypass in PyJWT versions prior to 2.13.0 allows remote attackers to forge valid JSON Web Tokens by exploi

CVE-2026-103001 MEDIUM POC
6.5 Sep 30

Reuse of a caller-supplied options mapping in PyJWT 2.11.0 through 2.13.0 can silently leave registered-claim verificati

CVE-2026-102265 MEDIUM POC
5.3 Sep 28

Malformed JSON Web Token headers can cause an uncaught RecursionError in PyJWT 2.13.0 through versions before 2.14.0, re

CVE-2026-48525 MEDIUM POC
5.3 May 28

Uncontrolled resource consumption in PyJWT 2.8.0-2.12.1 exposes any service that verifies detached JWS tokens to unauthe

CVE-2026-102268 CRITICAL
9.1 Sep 28

Signature forgery in PyJWT before 2.14.0 allows an attacker who knows a target's asymmetric public key to forge HMAC-aut

CVE-2026-102267 CRITICAL
9.1 Sep 28

JWKS trust-boundary bypass in PyJWT's PyJWKClient allows a configured trusted JWKS endpoint that returns an HTTP 3xx red

CVE-2026-48524 LOW POC
3.7 May 28

Unconstrained outbound JWKS requests in PyJWT's PyJWKClient.get_signing_key() allow unauthenticated remote attackers to

Vendor StatusVendor

SUSE

Severity: Moderate
Product Status
SUSE Linux Enterprise Desktop 15 SP7 Affected
SUSE Linux Enterprise High Performance Computing 12 Affected
SUSE Linux Enterprise Micro 5.5 Affected
SUSE Linux Enterprise Module for Basesystem 15 SP7 Affected
SUSE Linux Enterprise Module for Python 3 15 SP7 Affected

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy