Skip to main content

PyJWT EUVDEUVD-2026-88536

| CVE-2026-102269 MEDIUM
Incorrect Behavior Order: Validate Before Canonicalize (CWE-180)
2026-09-28 GitHub_M GHSA-hxm8-2xgr-2p9m
5.4
CVSS 3.1 · NVD
View

Attack ChainAIDerived

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

  1. Access
    Obtain a revoked or blocklisted JWT
  2. Delivery
    Append non-Base64URL characters to signature segment
  3. Exploit
    Modified token decodes to identical signature bytes and still verifies
  4. Execution
    Serialized token evades raw-token revocation blocklist
  5. Impact
    Regain access with revoked credential

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization Leading special element handling
Exploitation Conditions

Requires the application to use PyJWT < 2.14.0 AND to enforce token revocation/blocklisting by matching the raw, serialized token string rather than a claim such as jti. The attacker must already possess a valid-but-revoked (or otherwise blocklisted) token whose signature still verifies. Exploitation is LIMITED by this non-default architecture (PyJWT does not itself provide revocation), which drives CVSS AC:H; applications that revoke by claim/identifier, use short-lived tokens without a blocklist, or perform no raw-token comparison are unaffected. No user interaction or privileges are needed beyond holding the target token.

Impact

This is a real but low-severity defense-in-depth flaw, not a high-priority emergency. The CVSS 3.1 vector (AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N, base 4.8) is internally consistent with the described impact: network-reachable, no privileges, but high complexity because exploitation depends on a specific application architecture (raw-token/string-based JWT revocation or blocklisting) rather than PyJWT defaults. The core impact is an integrity/access-control failure - a revoked or blocklisted token can be reissued in a non-canonical serialization that still verifies but evades string-match revocation - so I lean toward C:N/I:L rather than the vendor's C:L/I:L. There is no EPSS score, no CISA KEV listing, and no standalone public exploit (the fix commit ships only a unit test), so exploitation status is 'no public exploit identified at time of analysis.' Signals do not conflict; they converge on a genuinely narrow-trigger issue in an extremely widely-used library. Note the vendor 'Information Disclosure' tag is misleading - the mechanism is signature-segment malleability leading to revocation bypass (integrity), not data leakage.

Exploit ScenarioDerived

An attacker holds a JWT that has been revoked or added to a blocklist (e.g., after logout or credential compromise), where the application enforces revocation by matching the raw token string. The attacker appends non-Base64URL characters to the compact JWS signature segment; because PyJWT < 2.14.0 decodes it to the identical signature bytes, the modified token still passes signature verification while its serialized form no longer matches the blocklist entry, restoring access. No public exploit code is published, and CVSS complexity is High because it only works against applications using raw-token revocation.

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

PyJWT versions prior to 2.14.0 accept signature segments that are not canonical Base64URL, so a token whose compact JWS signature has non-alphabet characters appended still decodes to the same signature bytes and passes verification. The practical impact is limited: an attacker who already holds a valid-but-revoked token can craft an equivalent serialized string that bypasses revocation or blocklisting logic which matches on the raw token string rather than a claim such as jti. This is a low-severity defense-in-depth flaw (assessed CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N) that requires the application to compare raw serialized tokens for revocation. No public exploit identified at time of analysis.

RemediationAI

Vendor-released patch: 2.14.0 - upgrade PyJWT to 2.14.0 or later (pip install --upgrade 'pyjwt>=2.14.0'); the fix commit is e6f48401001609a8f99e71fcaf355fb895d508a8 and the release notes are at https://github.com/jpadilla/pyjwt/releases/tag/2.14.0, with the advisory at https://github.com/jpadilla/pyjwt/security/advisories/GHSA-hxm8-2xgr-2p9m. Where upgrading immediately is not possible, the effective compensating control is architectural rather than token-level: change revocation logic to key on a unique claim such as jti (or sub plus issued-at) instead of the raw serialized token string, which removes the raw-token comparison this flaw subverts - the trade-off is that jti must be present and unique in every token your issuer mints, so legacy tokens without jti need a migration path. Alternatively, enforce canonical-form validation at the boundary by re-encoding and rejecting any incoming compact JWS whose segments do not round-trip exactly, or prefer short-lived access tokens with no blocklist so revocation by raw string is unnecessary; these avoid the bypass but require custom validation code that the 2.14.0 upgrade deletes the need for.

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

JSON Web Signature (JWS) compact serialization is three Base64URL segments joined by dots (header.payload.signature), and Base64URL is a canonical encoding: a given byte sequence has exactly one valid textual representation. PyJWT's base64url_decode was lenient and ignored trailing characters outside the canonical Base64URL alphabet when decoding the signature segment, so appending junk such as '!!!!' produced the same decoded bytes as the genuine, unmodified signature. The library's own regression test (test_decode_rejects_non_canonical_crypto_segment) demonstrates exactly this: signature + '!!!!' previously decoded without error. The root cause class is CWE-180 (Incorrect Behavior Order: Validate Before Canonicalize) - the decoder accepted and parsed a segment before confirming it was canonical. The fix introduces _decode_base64url_segment, which enforces the exact Base64URL alphabet, rejects segments whose length modulo 4 equals 1, and re-encodes the decoded bytes to confirm base64url_encode(decoded) == segment, raising DecodeError('Invalid ... padding') on any mismatch. The commit also tightened header and payload segment handling and updated compressed-JWT test vectors to canonical (unpadded, URL-safe) form.

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 5.4 MEDIUM
AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N
vuln.today AI 3.7 LOW

Network-reachable and no auth to trigger (PR:N), but AC:H because it needs raw-token revocation architecture plus a revoked token; impact is integrity-only revocation bypass, so I:L and C:N/A:N.

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

Primary rating from Vendor (GitHub_M).

CVSS VectorNVD

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

Lifecycle Timeline

3
CVSS changed
Oct 06, 2026 - 19:07 NVD
4.8 (MEDIUM) 5.4 (MEDIUM)
Patch available
Sep 28, 2026 - 22:02 EUVD
CVE Published
Sep 28, 2026 - 20:27 cve.org
MEDIUM 4.8

DescriptionNVD

PyJWT is a Python implementation of JSON Web Token standards. Prior to 2.14.0, PyJWT signature segment is affected because signature segment decoding accepts characters outside the canonical Base64URL representation. This occurs when non-Base64URL characters are appended to a valid compact JWS signature segment. As a result, base64url_decode produces the same signature bytes for different serialized segments. Consequently, raw-token revocation checks can fail to recognize an equivalent modified token. 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 91% exploitable
Prevalence
Ubiquitous
PyJWT is the de-facto standard JWT library across the Python ecosystem
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

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

Attack Technique

Information disclosure occurs when an application unintentionally exposes sensitive data that aids attackers in reconnaissance or directly compromises security.

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