Skip to main content

oauthlib CVE-2026-49265

| EUVDEUVD-2026-98833 MEDIUM
Observable Timing Discrepancy (CWE-208)
2026-09-29 https://github.com/oauthlib/oauthlib GHSA-xpv3-w29h-x7cv PYSEC-2026-4114
6.8
CVSS 3.1 · Vendor: https://github.com/oauthlib/oauthlib
View

Attack ChainAIDerived

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

  1. Access
    Intercept authorization_code via URI-scheme hijack
  2. Delivery
    Send repeated timed /token requests
  3. Exploit
    Measure response-time timing oracle
  4. Execution
    Recover code_verifier character-by-character
  5. Persist
    Redeem code for access token
  6. Impact
    Account takeover

Vulnerability Assessment

Weakness
CWE
ASVS 5.0
V6 - Authentication Timing attack prevention
Exploitation Conditions

Requires the target to use oauthlib's OAuth2 Authorization Code Grant with PKCE (RFC 7636) validation - the vulnerable code_challenge_method_plain / code_challenge_method_s256 comparison in authorization_code.py - on a vulnerable version (>=3.0.0, <4.0.0). Exploitation is heavily limited: the attacker must first independently obtain a valid authorization_code (e.g. via custom-URI-scheme hijacking, reflected in UI:R), must be able to issue and precisely time a very large volume of /token requests, and must complete character-by-character verifier recovery within the lifetime of a SINGLE-USE authorization code - which, combined with real-world network jitter dwarfing the nanosecond-per-call timing delta, makes practical exploitation marginal. Mitigated entirely by upgrading to oauthlib 4.0.0.

Impact

This is a genuine but low-real-world-risk defense-in-depth issue whose signals point consistently downward despite a mid-range CVSS. The vendor CVSS 3.1 vector (6.8, AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N) already encodes the key limiter as AC:H, and the C:H/I:H impact reflects the best-case downstream outcome (full account takeover) only IF the code_verifier is successfully recovered. No EPSS score, no CISA KEV listing, and no weaponized public exploit accompany this CVE - the 'Proof of Concept' in the advisory is a LOCAL Python microbenchmark (37ms delta over 10 MILLION iterations with network jitter deliberately removed), not a working remote exploit that recovers a verifier. The advisory author explicitly downgrades practical exploitability, noting that authorization codes are single-use (they expire long before a network-based char-by-char recovery could complete) and that real-world network noise swamps the nanosecond-per-call timing difference. Net: the C:H/I:H rating describes a theoretical worst case, while AC:H plus the single-use-code constraint make this closer to a code-hygiene fix than an urgent, actively-threatened flaw. Prioritize the routine upgrade to 4.0.0, but this is not a fire-drill.

Exploit ScenarioDerived

An attacker who has already intercepted an authorization_code (e.g. via custom-URI-scheme hijacking on a mobile client) but lacks the PKCE code_verifier sends many timed requests to the /token endpoint, measuring server response time to infer, character by character, how much of their guessed verifier matches the stored challenge, ultimately reconstructing it to redeem the code for an access token. No public working exploit exists - the referenced PoC is only a local timing microbenchmark, and single-use code expiry plus network noise make end-to-end recovery largely theoretical.

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

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

Alert me

AnalysisAIv1 – Sep 29, 2026

PKCE verifier validation in oauthlib 3.0.0 through 3.x compares the client-supplied code_verifier against the stored challenge using Python's short-circuiting == operator, producing a measurable timing oracle (CWE-208) that could in principle allow character-by-character recovery of the verifier. The attack is remote and unauthenticated per the assessed vector (AV:N/PR:N) but requires user interaction and is heavily constrained: the attacker must first independently obtain a valid single-use authorization_code, then issue and precisely time a very large volume of /token requests within that code's short lifetime, with nanosecond-scale per-call deltas in practice dwarfed by normal network jitter. At CVSS 6.8 (AC:H) with no public exploit code and no evidence of active exploitation, this is a genuine defense-in-depth defect rather than a practical account-takeover path, and it is fully resolved by upgrading to oauthlib 4.0.0.

RemediationAI

Upgrade oauthlib to 4.0.0 or later (pip install --upgrade 'oauthlib>=4.0.0'); this is the vendor-released patch and replaces the vulnerable == comparisons in both code_challenge_method_plain and code_challenge_method_s256 with hmac.compare_digest(). The fix is delivered via https://github.com/oauthlib/oauthlib/pull/963 and commit 40b0ab56da3682c2484a4b78bbff309f8025d950, and is described in the advisory at https://github.com/oauthlib/oauthlib/security/advisories/GHSA-xpv3-w29h-x7cv. If a version bump cannot be scheduled immediately, the minimal compensating control is to apply the upstream commit as a vendored patch - a two-line change that is low risk and requires no configuration changes. Additional hardening that shrinks the practical attack window, with trade-offs: enforce strict single-use authorization codes and aggressively short code lifetimes (already required by RFC 6749 but often loosely implemented) to make character-by-character recovery infeasible within the code's validity, at the cost of failing clients that retry token requests after transient errors; rate-limit or throttle the /token endpoint per client and per source IP to frustrate the statistically large sample of requests the timing oracle needs, accepting that legitimate high-volume deployments may need tuning; and eliminate the upstream credential-theft prerequisite by migrating OAuth clients away from custom URI scheme redirects to claimed HTTPS redirect URIs as recommended by RFC 8252, which requires client-side application changes. Note that restricting the server to code_challenge_method=S256 alone is not a complete mitigation, since the S256 comparison was vulnerable in the same way before the patch; and no configuration flag in affected oauthlib versions switches the comparison to constant time.

Affected VersionsENISA

oauthlib 3.0.0, < 4.0.0

Affected Packages

pypi oauthlib fix: 4.0.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

The affected code lives in oauthlib's OAuth 2.0 Authorization Code Grant implementation (oauthlib/oauth2/rfc6749/grant_types/authorization_code.py), specifically the PKCE (RFC 7636) helper functions code_challenge_method_plain and code_challenge_method_s256. Under PKCE, a client sends a derived code_challenge with the authorization request and must later present the original code_verifier at the token endpoint; the server recomputes the challenge (for S256, base64url(SHA-256(verifier)) with trailing '=' stripped, per the diff, and for plain, the raw verifier) and compares it to the stored value. Both helpers used Python's == operator, which short-circuits: it returns False immediately when lengths differ and otherwise compares bytes left to right until the first mismatch. That behavior belongs to CWE-208 (Observable Timing Discrepancy): comparison cost grows with the length of the matching prefix, so an adversary who can measure response times precisely enough can infer the correct prefix incrementally and reconstruct the verifier. The upstream fix replaces both comparisons with hmac.compare_digest(), a constant-time primitive, and also imports the hmac module in the affected file. The package is distributed as CPE pkg:pip/oauthlib, with vulnerable ranges >= 3.0.0 and < 4.0.0, meaning the exposure applies to any Python service that embeds this library (Flask/Django OAuth providers, resource servers, API gateways) and enables PKCE on its token endpoint.

Know when Python 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 (https://github.com/oauthlib/oauthlib) PRIMARY 6.8 MEDIUM
AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N
vuln.today AI 6.8 MEDIUM

Network-reachable and unauthenticated (AV:N/PR:N) but AC:H because timing recovery is nanosecond-scale and must beat single-use-code expiry; UI:R for the code interception; C:H/I:H reflect resulting account takeover, A:N.

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

Primary rating from Vendor (https://github.com/oauthlib/oauthlib).

CVSS VectorVendor: https://github.com/oauthlib/oauthlib

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

DescriptionCVE.org

Summary

A timing side-channel vulnerability exists in the PKCE (RFC 7636) implementation of the Authorization Code Grant flow. The code_challenge_method_plain function uses Python's standard == operator for string comparison instead of a constant-time comparison function, potentially allowing timing-based attacks.

Affected Component

  • File: oauthlib/oauth2/rfc6749/grant_types/authorization_code.py
  • Functions: code_challenge_method_plain, code_challenge_method_s256
  • Vulnerability Type: CWE-208 (Observable Timing Discrepancy)

Technical Details

Python's == operator uses short-circuit evaluation when comparing strings:

  1. Returns False immediately if lengths differ
  2. Compares characters left-to-right, stopping at first mismatch

This means comparison time varies linearly with the length of the common prefix between the attacker-supplied verifier and the stored challenge, creating a measurable timing oracle.

Proof of Concept

Tested locally against oauthlib source (network jitter eliminated to isolate pure Python execution time):

InputResultTime (10M iterations)
Wrong first char (B + A*49)Fast reject0.34106s
49 chars correct (A*49 + B)Deep compare0.37847s
Difference0.03741s

The ~37ms delta over 10M iterations corresponds to nanosecond-level differences per call, which are statistically exploitable under controlled conditions.

Attack Scenario

  1. Attacker intercepts authorization_code via Custom URI Scheme Hijacking
  2. PKCE blocks token request - attacker lacks code_verifier
  3. Attacker sends repeated requests to /token endpoint measuring response times
  4. Using timing oracle, attacker recovers code_verifier character by character
  5. Attacker obtains Access Token → Account Takeover

> Note: Practical exploitability is limited due to the single-use nature of > authorization codes and real-world network noise. However, the vulnerable > pattern should be corrected as a defense-in-depth measure.

Recommended Fix

Replace == with hmac.compare_digest() for constant-time comparison:

cr: Elvin Latifli

Threat Intelligence Overview

EPSS Score
0.4%
Top 70% exploitable
Prevalence
High
oauthlib is a core Python OAuth library backing requests-oauthlib, Django OAuth Toolkit, Flask
Threat Intel
1
1 sources
Data Quality
6 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.4%
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· derived
None
System Exposure· derived
Open
Automatable· derived
No
Human Impact· derived
Medium

Priority Score

34
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +34
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 Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-49869 CRITICAL POC
10.0 Jun 26

Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

Vendor StatusVendor

SUSE

Severity: Moderate
Product Status
SUSE Linux Enterprise Module for Public Cloud 15 SP4 Affected
SUSE Linux Enterprise Server 15 SP4 Affected
SUSE Linux Enterprise Server for SAP Applications 15 SP4 Affected
SUSE Linux Enterprise High Performance Computing 15 SP4 Affected
SUSE Manager Server 4.3 Affected

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