PHP2Shell: Read our blog on the critical RCE vulnerabilities affecting 70% of the Internet
Vulnerability DatabaseCVE-2026-102275

CVE-2026-102275: 
CBL Mariner vulnerability analysis and mitigation

Overview

CVE-2026-102275 is an authentication bypass vulnerability in PyJWT, a Python implementation of JSON Web Token standards, caused by improper verification of OKP (Octet Key Pair) private JWK components. The OKPAlgorithm.from_jwk() function in jwt/algorithms.py accepts private JWKs where the declared public key (x) does not correspond to the supplied private key (d), allowing an attacker to supply mismatched key components. Affected versions are PyJWT 2.1.0 through 2.14.0 (Ed25519 from 2.1.0, Ed448 from 2.2.0); the issue is fixed in version 2.15.0. The CVSS v3.1 base score is 6.5 (Medium) per the GitHub Security Advisory, though NVD scores it 8.2 (High) (GitHub Advisory, Red Hat).

Technical details

The root cause is a logic flaw (CWE-345: Insufficient Verification of Data Authenticity; CWE-347: Improper Verification of Cryptographic Signature; CWE-348: Use of Less Trusted Source) in jwt/algorithms.py. When a private OKP JWK is imported, the code decodes both x and d, but when d is present it constructs the private key solely from d without deriving the corresponding public key and comparing it to x. This means a JWK can declare one public key identity (via x) while PyJWT performs all cryptographic operations using a different private key (derived from d). In DPoP (RFC 9449) integrations that compute JWK thumbprints from x and then pass the full JWK — including d — to PyJWK.from_dict() without rejecting private key material, an attacker can craft a malformed JWK combining a legitimate user's x with the attacker's d, causing the thumbprint check to pass while signature verification uses the attacker's key (GitHub Advisory, Fix Commit).

Impact

Successful exploitation allows an attacker who has stolen a sender-constrained access token (DPoP-bound via cnf.jkt) to use that token without possessing the legitimate holder's private key, effectively bypassing the sender-constraint protection. The primary impact is high integrity loss — the attacker can impersonate the legitimate token holder and perform any actions the stolen token's scope permits — with low confidentiality impact from accessing protected resources. Availability is not affected, and exploitation is limited to applications using PyJWT for OKP/EdDSA DPoP verification that also fail to reject private key parameters in proof headers (GitHub Advisory, Red Hat Bugzilla).

Exploitability

A proof-of-concept exploit (a complete, runnable Python script) is publicly available in the GitHub Security Advisory, demonstrating the full attack flow including token creation, malformed JWK construction, and successful verification bypass (GitHub Advisory). The EPSS score is approximately 0.00137 (low probability of exploitation in the near term), and there is no evidence of active in-the-wild exploitation or CISA KEV catalog inclusion as of the advisory date. Exploitation is not fully automated (NVD SSVC: automatable: no) because it requires a prior step of stealing a valid sender-constrained access token and knowledge of the legitimate user's public key. No threat actor attribution has been reported. The vulnerability was reported by researcher ze3tar (GitHub Advisory).

Exploitation steps

  1. Prerequisite — Steal a sender-constrained access token: Obtain a valid DPoP-bound access token for a legitimate user (e.g., via phishing, token leakage, or interception). The token's cnf.jkt claim contains the SHA-256 thumbprint of the legitimate user's Ed25519/Ed448 public key.
  2. Derive the legitimate user's public key (x): Recover the legitimate user's public JWK (e.g., from a public endpoint, the token's associated metadata, or by reversing the cnf.jkt thumbprint if the key is known).
  3. Generate an attacker Ed25519 keypair: Use Ed25519PrivateKey.generate() to create a fresh attacker keypair with attacker_x (public) and attacker_d (private).
  4. Construct a malformed JWK: Build a JWK that combines the legitimate user's x with the attacker's d: {"kty": "OKP", "crv": "Ed25519", "alg": "EdDSA", "x": "<legitimate_x>", "d": "<attacker_d>"}.
  5. Verify thumbprint match: Compute the RFC 7638 JWK thumbprint over {crv, kty, x} of the malformed JWK — since d is excluded from the thumbprint calculation, it still matches the stolen token's cnf.jkt.
  6. Create a DPoP proof signed with the attacker's private key: Call jwt.encode(proof_claims, attacker_private_key, algorithm='EdDSA', headers={'jwk': mismatched_proof_jwk, 'typ': 'dpop+jwt'}) with required DPoP claims (htm, htu, iat, jti, ath).
  7. Submit to the resource server: Send the stolen access token and the attacker-crafted DPoP proof to the protected resource endpoint. A vulnerable server will: (a) verify the thumbprint from x — passes; (b) call PyJWK.from_dict(malformed_jwk) — PyJWT imports the attacker's private key from d; (c) verify the DPoP proof signature — passes because the proof was signed with the attacker's key, which PyJWT imported. The server accepts the request as the legitimate user (GitHub Advisory).

Indicators of compromise

  • Network: Unexpected API requests using DPoP-bound tokens where the DPoP proof JWK header contains both x and d parameters (private key material should never appear in a DPoP proof header per RFC 9449 §4.2).
  • Network: Repeated access attempts to protected resources using the same cnf.jkt-bound access token from different IP addresses or user agents, suggesting token theft and reuse.
  • Logs: Application logs showing DPoP proof JWKs with d, p, q, dp, dq, qi, or k fields present in the jwk header of incoming proof JWTs — these should be rejected by RFC-compliant implementations.
  • Logs: Successful authentication events where the signing key identity (derived from d) does not match the declared public key (x) in the DPoP proof JWK — detectable only if the application logs JWK components.
  • Application Behavior: InvalidKeyError exceptions from PyJWT after upgrading to 2.15.0 on previously accepted requests, indicating prior exploitation attempts that would have succeeded on older versions (GitHub Advisory).

Mitigation and workarounds

The primary remediation is to upgrade PyJWT to version 2.15.0 or later, which introduces a fix in jwt/algorithms.py (commit 3cd9ceec) that derives the public key from d, compares it to x, and raises InvalidKeyError on mismatch (PyJWT Release, Fix Commit). As an immediate workaround for applications that cannot upgrade, implement validation to reject any DPoP proof JWK header containing private key parameters (d, p, q, dp, dq, qi, k) before passing the JWK to PyJWT — this is also required by RFC 9449 §4.2 and §4.3. Applications that do not use OKP/EdDSA keys or do not implement DPoP are not affected by the demonstrated attack scenario (GitHub Advisory).

Community reactions

The PyJWT maintainers independently reproduced the issue, confirmed the fix on master, and published the advisory alongside the 2.15.0 release on September 23, 2026 (GitHub Advisory). Red Hat tracked the issue via Bugzilla (Bug 2542701) and published a security advisory, indicating downstream impact on Red Hat products shipping PyJWT (Red Hat Bugzilla). The advisory notes that a public example of a vulnerable DPoP composition exists in StrongDM's agentic-auth Flask middleware, which computes OKP thumbprints from x and passes the full JWK to PyJWK.from_dict() without rejecting d. Microsoft also acknowledged the vulnerability through its Security Response Center (Microsoft MSRC).

Additional resources

Linux Distribution fix status

Fix availability across major Linux distributions and their releases.

Debian

Fixed

bookworm

pyjwt

Affected

sid

pyjwt: 2.15.0-1

Fixed

trixie

pyjwt

Affected

Ubuntu

Affected

bionic (esm-infra)

pyjwt

Not Affected

devel

pyjwt

Affected

focal (esm-infra)

pyjwt

Not Affected

jammy

pyjwt

Affected

noble

pyjwt

Affected

resolute

pyjwt

Affected

xenial (esm-infra-legacy)

pyjwt

Not Affected

RHEL / CentOS

Affected

RHEL 8

Not Affected

RHEL 9

fence-agents.src

Affected

RHEL 10

fence-agents.src

Affected

Source: This report was generated using AI

Related CBL Mariner vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-98383HIGH7.1
  • Linux Kernel logoLinux Kernel
  • kernel-64k-modules-internal
NoYesOct 09, 2026
CVE-2026-98381HIGH7.1
  • Linux Kernel logoLinux Kernel
  • kernel-zfcpdump-modules-partner
NoYesOct 09, 2026
CVE-2026-98382MEDIUM5.1
  • Linux Kernel logoLinux Kernel
  • kernel-64k-debug
NoYesOct 09, 2026
CVE-2026-98380MEDIUM5.1
  • Linux Kernel logoLinux Kernel
  • linux-nvidia-tegra
NoYesOct 09, 2026
CVE-2026-98384LOW3.3
  • Linux Kernel logoLinux Kernel
  • linux-drivers-sound
NoYesOct 09, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management