Skip to main content

PyJWT EUVDEUVD-2026-88547

| CVE-2026-102275 HIGH
Insufficient Verification of Data Authenticity (CWE-345)
2026-09-28 GitHub_M GHSA-x33g-cr3x-6449
8.2
CVSS 3.1 · NVD
View

Attack ChainAIDerived

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

  1. Access
    Steal victim sender-constrained DPoP token
  2. Delivery
    Forge OKP JWK: victim x, attacker d
  3. Exploit
    PyJWT imports attacker key, skips x/d check
  4. Execution
    Sign DPoP proof with attacker key
  5. Impact
    Replay stolen token impersonating victim

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A08:2025 - Software or Data Integrity Failures
ASVS 5.0
V15 - Secure Coding and Architecture Data authenticity verification
Exploitation Conditions

Exploitation requires three specific conditions, not a default-configuration remote hit: (1) the target application uses PyJWT (2.1.0-2.14.0) OKPAlgorithm.from_jwk / PyJWK.from_dict to import OKP (Ed25519/Ed448) private JWKs; (2) the integration accepts full JWK private-key material - specifically the d parameter - from an attacker-controlled source such as a DPoP proof header, without rejecting private components; and (3) the attacker already possesses a stolen sender-constrained (e.g. DPoP-bound) token whose cnf.jkt thumbprint is computed from x. Limiting factors: the attack fails against integrations that only accept public JWKs in proof headers, that reject JWKs containing d, or that verify key consistency; it also requires prior theft of a valid bound token. Standard signature-verification use of PyJWT with trusted server-side keys is NOT affected.

Impact

Signals are mixed and point to a real but conditional threat rather than a mass-exploitation emergency. The vendor CVSS 3.1 vector (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H, 8.2 High) implies trivial unauthenticated network exploitation, but the description and GHSA advisory make clear this only matters when an integration accepts private-key JWK parameters (d) from an attacker-controlled DPoP proof header AND the attacker already possesses a stolen sender-constrained token - so the practical complexity is higher than AC:L suggests. SSVC agrees it is not a drop-in mass exploit: Exploitation=poc, Automatable=no, Technical Impact=partial. EPSS is very low (0.14%, 3rd percentile) and the CVE is NOT in CISA KEV, consistent with no observed widespread exploitation. A working PoC exists (publicly available exploit code), confirming the key-confusion is real and reproducible, but PoC availability is not active exploitation. Net: this is a genuine authentication/identity-confusion flaw worth prioritizing specifically for services using PyJWT for DPoP or other OKP private-JWK import flows, but it is not an indiscriminate internet-wide risk. Note the conflict to verify: CVSS AC:L understates the real-world precondition (stolen token + permissive integration), so raw 8.2 overstates realistic risk for most deployments.

Exploit ScenarioDerived

An attacker who has intercepted a victim's sender-constrained (DPoP) access token crafts an OKP JWK containing the victim's legitimate public key x together with the attacker's own private key d, and submits it in a DPoP proof header. Because PyJWT's OKPAlgorithm.from_jwk never checks that x corresponds to d, it builds the key from the attacker's d while the RFC 7638 thumbprint still matches the victim binding, so the attacker signs a valid proof and replays the stolen token without ever holding the victim's private key. A public PoC demonstrates this end-to-end (stolen_sender_constrained_token_accepted: true).

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
1 public PoC Patch available 0.1% exploitation probability (EPSS)

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

Alert me

AnalysisAIv2 – Oct 06, 2026

Improper validation in PyJWT 2.1.0 through 2.14.0 allows an attacker who already holds a stolen sender-constrained (DPoP-bound) access token to replay it without possessing the legitimate holder's private key, because OKPAlgorithm.from_jwk imports an Ed25519/Ed448 private JWK from the d parameter without checking that the public key derived from d matches the declared x. An attacker-supplied JWK that pairs the victim's x with the attacker's own d therefore satisfies RFC 7638 thumbprint binding (cnf.jkt) while all signing operations use the attacker's key. Publicly available exploit code exists (a public gist reproducer), but EPSS is only 0.14% (3rd percentile) and there is no KEV listing - this is a conditional, integration-dependent flaw rather than a default-configuration remote compromise, and standard signature-verification use of PyJWT with trusted server-side keys is not affected.

Earlier versions of this analysis (1)
v1 Sep 28, 2026 - 21:17 CVSS 6.5

PyJWT 2.1.0 through 2.14.x fails to verify that the public component embedded in an OKP (Ed25519/Ed448) private JWK actually corresponds to the supplied private key material, so OKPAlgorithm.from_jwk returns a key object whose declared identity (x) can diverge from the key used for cryptographic operations (d). In integrations that parse private-key JWK parameters out of an attacker-controllable proof header instead of rejecting them and that rely on sender-constrained / proof-of-possession token binding, an unauthenticated remote attacker who already holds a stolen but otherwise valid token can present proof material signed with their own key and have it accepted without the legitimate private key, giving an integrity-only impact rated medium (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N). The issue is not listed in CISA KEV and no public exploit code has been identified at time of analysis; the root cause is remediated in PyJWT 2.15.0.

RemediationAI

Upgrade PyJWT to 2.15.0 (pip install -U PyJWT) - vendor-released patch: 2.15.0 - which is the fix commit https://github.com/jpadilla/pyjwt/commit/3cd9ceec33ced359decbad75b413ad668ae6332c; that change derives the public key from d and raises InvalidKeyError("Public key does not match private key") when it differs from x. Where upgrading is not immediately possible, apply these specific compensating controls in the integration layer, each with trade-offs: (1) reject any DPoP proof or other attacker-supplied JWK that contains a "d" (or any private-key parameter) before handing it to PyJWK.from_dict, and accept only public JWKs for proof verification - this defeats the attack entirely but will break any (non-standard) workflow that legitimately expects private JWK material from a request header; (2) wrap OKPAlgorithm.from_jwk/PyJWK.from_dict and independently reconstruct the public key from d, aborting if it does not equal x - low overhead, but a per-call check that must be applied everywhere the library is used; (3) treat DPoP/thumbprint binding as one factor rather than the sole control for sender-constrained tokens (short token lifetimes, holder-of-key re-binding on sensitive operations, anomaly detection on key-substitution patterns) - reduces blast radius but does not eliminate acceptance of stolen tokens. Note that this is not a memory-safety or RCE issue and that standard JWS/JWT signature verification with server-trusted keys needs no change; remediation effort should be prioritised on DPoP/OAuth resource servers and any endpoint that parses client-supplied JWKs.

Affected VersionsENISA

pyjwt 2.1.0, < 2.15.0

Affected Packages

pypi pyjwt fix: 2.15.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 JWT/JWK/JWS standards, and CVE-2026-102275 is a CWE-345 (Insufficient Verification of Data Authenticity) defect in the OKP key-import path of jwt/algorithms.py. Octet Key Pair (OKP) JWKs for Ed25519/Ed448 carry a public key in x and, optionally, a private seed in d; correct import must derive the public key from d and reject the JWK if it does not equal x. PyJWT instead parsed x only to confirm its presence and then constructed Ed25519PrivateKey/Ed448PrivateKey directly from d, so a JWK declaring one identity (x) could perform cryptographic operations under a different identity (d). The impact materialises in sender-constrained token schemes such as DPoP, where an access token binds to a key via the RFC 7638 JWK thumbprint in the cnf.jkt claim: the thumbprint is computed from x, so an attacker who supplies the legitimate x plus their own d passes the binding check while signing DPoP proofs with their own key. The defect was present since OKP private-JWK import was introduced (Ed25519 from PyJWT 2.1.0, Ed448 from 2.2.0) and persisted through 2.14.0; the affected package is tracked as CPE cpe:2.3:a:jpadilla:pyjwt:*:*:*:*:*:*:*:* and as EUVD-2026-88547 (pyjwt 2.1.0, < 2.15.0).

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 8.2 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N
vuln.today AI 6.5 MEDIUM

Attacker is unauthenticated (no legitimate private key) so PR:N, but needs a permissive DPoP integration plus a previously stolen token, so AC:H; impact is primarily impersonation/integrity (I:H) with limited confidentiality (C:L).

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

Primary rating from Vendor (GitHub_M).

CVSS VectorNVD

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

Lifecycle Timeline

4
Severity Changed
Oct 06, 2026 - 18:22 NVD
MEDIUM HIGH
CVSS changed
Oct 06, 2026 - 18:22 NVD
6.5 (MEDIUM) 8.2 (HIGH)
Patch available
Sep 28, 2026 - 22:02 EUVD
CVE Published
Sep 28, 2026 - 20:46 cve.org
MEDIUM 6.5

DescriptionNVD

PyJWT is a Python implementation of JSON Web Token standards. From 2.1.0 until 2.15.0, PyJWT OKPAlgorithm.from_jwk in jwt/algorithms.py is affected because private-JWK import path does not compare the public key derived from d with x. This occurs when an OKP private JWK supplies non-corresponding x and d components. As a result, identity derived from x can differ from operations performed with d. Consequently, if an integration also accepts private key parameters from a proof header without rejecting them, an attacker may use a stolen sender-constrained token without the legitimate private key. This issue is fixed in version 2.15.0.

Blast Radius

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

Ecosystem-wide dependent count for version 2.1.0.

Technical POC Analysis

CWE-345 (Insufficient Verification of Data Authenticity); the advisory also assigns CWE-348 (Use of Less Trusted Source).

Full technical POC analysis - root cause, step-by-step exploitation and patch breakdown - is part of the Pro and Business plans.

Latest POC

1 public PoC link from github

Sign in to open the public PoC links collected for this CVE.

Executive ViewAI

Why It Matters

A flaw in PyJWT versions 2.1.0 through 2.14.0 can allow an attacker who already holds a stolen DPoP-bound access token to replay it without the legitimate holder's private key, weakening sender-constrained token protections for applications that use this library. Publicly available exploit code exists, but exploitation depends on a stolen token and specific integration patterns rather than default remote compromise, so exposure is concentrated in services that validate DPoP-bound tokens. Leadership should direct affected teams to patch PyJWT and review token-binding controls because a bypass could enable unauthorized API access using compromised tokens.

Business Impact: Medium
Compensating Controls

Apply vendor patch.

Threat Intelligence Overview

EPSS Score
0.1%
Top 97% exploitable
Prevalence
High
PyJWT is among the most widely deployed Python JWT libraries
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 HIGH
CISA KEV No
Public POC Yes
EPSS 0.1%
Patch available Yes
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.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
Scheduled
Exploitation
Poc
System Exposure· derived
Open
Automatable
No
Human Impact
Medium
Technical Impact
Partial

Priority Score

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

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-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-101917 HIGH
7.5 Sep 28

Unauthenticated attackers can amplify outbound HTTP traffic from any application that validates JWTs with PyJWT's PyJWKC

CVE-2017-11424 HIGH
7.5 Aug 24

In PyJWT 1.5.0 and below the `invalid_strings` check in `HMACAlgorithm.prepare_key` does not account for all PEM encoded

Vendor StatusVendor

SUSE

Severity: Moderate
Product Status
SUSE Linux Enterprise Desktop 15 SP7 Affected
SUSE Linux Enterprise High Performance Computing 12 Not-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