
Cloud Vulnerability DB
A community-led vulnerabilities database
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).
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).
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).
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).
cnf.jkt claim contains the SHA-256 thumbprint of the legitimate user's Ed25519/Ed448 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).Ed25519PrivateKey.generate() to create a fresh attacker keypair with attacker_x (public) and attacker_d (private).x with the attacker's d: {"kty": "OKP", "crv": "Ed25519", "alg": "EdDSA", "x": "<legitimate_x>", "d": "<attacker_d>"}.{crv, kty, x} of the malformed JWK — since d is excluded from the thumbprint calculation, it still matches the stolen token's cnf.jkt.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).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).x and d parameters (private key material should never appear in a DPoP proof header per RFC 9449 §4.2).cnf.jkt-bound access token from different IP addresses or user agents, suggesting token theft and reuse.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.d) does not match the declared public key (x) in the DPoP proof JWK — detectable only if the application logs JWK components.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).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).
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).
Fix availability across major Linux distributions and their releases.
bionic (esm-infra)
pyjwt
devel
pyjwt
focal (esm-infra)
pyjwt
jammy
pyjwt
noble
pyjwt
resolute
pyjwt
xenial (esm-infra-legacy)
pyjwt
Source: This report was generated using AI
Free Vulnerability Assessment
Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.
Get a personalized demo
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
"We know that if Wiz identifies something as critical, it actually is."