CVE-2026-49265
OAuthLib: Timing Attack Vulnerability in PKCE code_verifier Comparison
OAuthLib is an implementation of the OAuth request-signing logic for Python 3.6+. From 3.0.0 until 4.0.0, OAuthLib's PKCE checks in oauthlib/oauth2/rfc6749/grant_types/authorization_code.py compare attacker-supplied code_verifier values with stored challenges using ordinary string equality in code_challenge_method_plain and code_challenge_method_s256. Because the comparison can return after a length difference or the first mismatching character, repeated token endpoint measurements can reveal common-prefix timing information that could potentially allow recovery of the code_verifier, unauthorized access-token acquisition, and account takeover. Practical exploitation requires an intercepted, single-use authorization code and enough measurements to overcome real-world network noise; the local timing benchmark does not establish practical remote account takeover, so the weakness remains a defense-in-depth concern. This issue is fixed in version 4.0.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
6.8
OAuthLib: Timing Attack Vulnerability in PKCE code_verifier Comparison
OAuthLib is an implementation of the OAuth request-signing logic for Python 3.6+. From 3.0.0 until 4.0.0, OAuthLib's PKCE checks in oauthlib/oauth2/rfc6749/grant_types/authorization_code.py compare attacker-supplied code_verifier values with stored challenges using ordinary string equality in code_challenge_method_plain and code_challenge_method_s256. Because the comparison can return after a length difference or the first mismatching character, repeated token endpoint measurements can reveal common-prefix timing information that could potentially allow recovery of the code_verifier, unauthorized access-token acquisition, and account takeover. Practical exploitation requires an intercepted, single-use authorization code and enough measurements to overcome real-world network noise; the local timing benchmark does not establish practical remote account takeover, so the weakness remains a defense-in-depth concern. This issue is fixed in version 4.0.0.
- Record
CVE-2026-49265- CVSS 3.1
- 6.8 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N - Weakness
- CWE-208
- Updated
- 2026-11-02
EUVDEUVD-2026-98833
6.8
OAuthLib is an implementation of the OAuth request-signing logic for Python 3.6+. From 3.0.0 until 4.0.0, OAuthLib's PKCE checks in oauthlib/oauth2/rfc6749/grant_types/authorization_code.py compare attacker-supplied code_verifier values with stored challenges using ordinary string equality in code_challenge_method_plain and code_challenge_method_s256. Because the comparison can return after a length difference or the first mismatching character, repeated token endpoint measurements can reveal common-prefix timing information that could potentially allow recovery of the code_verifier, unauthorized access-token acquisition, and account takeover. Practical exploitation requires an intercepted, single-use authorization code and enough measurements to overcome real-world network noise; the local timing benchmark does not establish practical remote account takeover, so the weakness remains a defense-in-depth concern. This issue is fixed in version 4.0.0.
- Record
EUVD-2026-98833- CVSS 3.1
- 6.8 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-xpv3-w29h-x7cv
6.8
Oauthlib: Timing Attack Vulnerability in PKCE code_verifier Comparison (CWE-208)
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:
- Returns
Falseimmediately if lengths differ - 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):
| Input | Result | Time (10M iterations) |
|---|---|---|
| Wrong first char (B + A*49) | Fast reject | 0.34106s |
| 49 chars correct (A*49 + B) | Deep compare | 0.37847s |
| Difference | | 0.03741s |
The ~37ms delta over 10M iterations corresponds to nanosecond-level differences per call, which are statistically exploitable under controlled conditions.
Attack Scenario
- Attacker intercepts
authorization_codevia Custom URI Scheme Hijacking - PKCE blocks token request — attacker lacks
code_verifier - Attacker sends repeated requests to
/tokenendpoint measuring response times - Using timing oracle, attacker recovers
code_verifiercharacter by character - 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
- Record
GHSA-xpv3-w29h-x7cv- CVSS 3.1
- 6.8 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N - Weakness
- CWE-208
- Updated
- 2026-11-02
NVD
6.8
OAuthLib is an implementation of the OAuth request-signing logic for Python 3.6+. From 3.0.0 until 4.0.0, OAuthLib's PKCE checks in oauthlib/oauth2/rfc6749/grant_types/authorization_code.py compare attacker-supplied code_verifier values with stored challenges using ordinary string equality in code_challenge_method_plain and code_challenge_method_s256. Because the comparison can return after a length difference or the first mismatching character, repeated token endpoint measurements can reveal common-prefix timing information that could potentially allow recovery of the code_verifier, unauthorized access-token acquisition, and account takeover. Practical exploitation requires an intercepted, single-use authorization code and enough measurements to overcome real-world network noise; the local timing benchmark does not establish practical remote account takeover, so the weakness remains a defense-in-depth concern. This issue is fixed in version 4.0.0.
- Record
CVE-2026-49265- CVSS 3.1
- 6.8 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N - Weakness
- CWE-208
- Updated
- 2026-11-02
OSV
6.8
OAuthLib: Timing Attack Vulnerability in PKCE code_verifier Comparison
OAuthLib is an implementation of the OAuth request-signing logic for Python 3.6+. From 3.0.0 until 4.0.0, OAuthLib's PKCE checks in oauthlib/oauth2/rfc6749/grant_types/authorization_code.py compare attacker-supplied code_verifier values with stored challenges using ordinary string equality in code_challenge_method_plain and code_challenge_method_s256. Because the comparison can return after a length difference or the first mismatching character, repeated token endpoint measurements can reveal common-prefix timing information that could potentially allow recovery of the code_verifier, unauthorized access-token acquisition, and account takeover. Practical exploitation requires an intercepted, single-use authorization code and enough measurements to overcome real-world network noise; the local timing benchmark does not establish practical remote account takeover, so the weakness remains a defense-in-depth concern. This issue is fixed in version 4.0.0.
- Record
CVE-2026-49265- CVSS 3.1
- 6.8 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N - Weakness
- CWE-208
- Updated
- 2026-11-02
OSVDEBIAN-CVE-2026-49265
6.8
OAuthLib is an implementation of the OAuth request-signing logic for Python 3.6+. From 3.0.0 until 4.0.0, OAuthLib's PKCE checks in oauthlib/oauth2/rfc6749/grant_types/authorization_code.py compare attacker-supplied code_verifier values with stored challenges using ordinary string equality in code_challenge_method_plain and code_challenge_method_s256. Because the comparison can return after a length difference or the first mismatching character, repeated token endpoint measurements can reveal common-prefix timing information that could potentially allow recovery of the code_verifier, unauthorized access-token acquisition, and account takeover. Practical exploitation requires an intercepted, single-use authorization code and enough measurements to overcome real-world network noise; the local timing benchmark does not establish practical remote account takeover, so the weakness remains a defense-in-depth concern. This issue is fixed in version 4.0.0.
- Record
DEBIAN-CVE-2026-49265- CVSS 3.1
- 6.8 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N - Updated
- 2026-11-02
Show 9 moreShow less
OSVGHSA-xpv3-w29h-x7cv
6.8
Oauthlib: Timing Attack Vulnerability in PKCE code_verifier Comparison (CWE-208)
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:
- Returns
Falseimmediately if lengths differ - 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):
| Input | Result | Time (10M iterations) |
|---|---|---|
| Wrong first char (B + A*49) | Fast reject | 0.34106s |
| 49 chars correct (A*49 + B) | Deep compare | 0.37847s |
| Difference | | 0.03741s |
The ~37ms delta over 10M iterations corresponds to nanosecond-level differences per call, which are statistically exploitable under controlled conditions.
Attack Scenario
- Attacker intercepts
authorization_codevia Custom URI Scheme Hijacking - PKCE blocks token request — attacker lacks
code_verifier - Attacker sends repeated requests to
/tokenendpoint measuring response times - Using timing oracle, attacker recovers
code_verifiercharacter by character - 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
- Record
GHSA-xpv3-w29h-x7cv- CVSS 3.1
- 6.8 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N - Weakness
- CWE-208
- Updated
- 2026-11-02
OSVPYSEC-2026-4114
6.8
Oauthlib: Timing Attack Vulnerability in PKCE code_verifier Comparison (CWE-208)
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:
- Returns
Falseimmediately if lengths differ - 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):
| Input | Result | Time (10M iterations) |
|---|---|---|
| Wrong first char (B + A*49) | Fast reject | 0.34106s |
| 49 chars correct (A*49 + B) | Deep compare | 0.37847s |
| Difference | | 0.03741s |
The ~37ms delta over 10M iterations corresponds to nanosecond-level differences per call, which are statistically exploitable under controlled conditions.
Attack Scenario
- Attacker intercepts
authorization_codevia Custom URI Scheme Hijacking - PKCE blocks token request — attacker lacks
code_verifier - Attacker sends repeated requests to
/tokenendpoint measuring response times - Using timing oracle, attacker recovers
code_verifiercharacter by character - 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
- Record
PYSEC-2026-4114- CVSS 3.1
- 6.8 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N - Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-49265
6.8
OAuthLib is an implementation of the OAuth request-signing logic for Python 3.6+. From 3.0.0 until 4.0.0, OAuthLib's PKCE checks in oauthlib/oauth2/rfc6749/grant_types/authorization_code.py compare attacker-supplied code_verifier values with stored challenges using ordinary string equality in code_challenge_method_plain and code_challenge_method_s256. Because the comparison can return after a length difference or the first mismatching character, repeated token endpoint measurements can reveal common-prefix timing information that could potentially allow recovery of the code_verifier, unauthorized access-token acquisition, and account takeover. Practical exploitation requires an intercepted, single-use authorization code and enough measurements to overcome real-world network noise; the local timing benchmark does not establish practical remote account takeover, so the weakness remains a defense-in-depth concern. This issue is fixed in version 4.0.0.
- Record
UBUNTU-CVE-2026-49265- CVSS 3.1
- 6.8 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N - Updated
- 2026-11-02
OSVAZL-108045 No score
CVE-2026-49265 affecting package python-oauthlib for versions less than 3.2.2-4
OAuthLib is an implementation of the OAuth request-signing logic for Python 3.6+. From 3.0.0 until 4.0.0, OAuthLib's PKCE checks in oauthlib/oauth2/rfc6749/grant_types/authorization_code.py compare attacker-supplied code_verifier values with stored challenges using ordinary string equality in code_challenge_method_plain and code_challenge_method_s256. Because the comparison can return after a length difference or the first mismatching character, repeated token endpoint measurements can reveal common-prefix timing information that could potentially allow recovery of the code_verifier, unauthorized access-token acquisition, and account takeover. Practical exploitation requires an intercepted, single-use authorization code and enough measurements to overcome real-world network noise; the local timing benchmark does not establish practical remote account takeover, so the weakness remains a defense-in-depth concern. This issue is fixed in version 4.0.0.
- Record
AZL-108045- Updated
- 2026-11-07
OSVopenSUSE-SU-2026:22103-1 No score
Security update for python-oauthlib
This update for python-oauthlib fixes the following issues:
- CVE-2026-49264: Oauthlib : Unsafe JSONP callback injection in RevocationEndpoint allows arbitrary JavaScript response generation (bsc#1283526).
- CVE-2026-49265: Oauthlib: Timing Attack Vulnerability in PKCE code_verifier Comparison (bsc#1283527).
- Record
openSUSE-SU-2026:22103-1- Updated
- 2026-11-02
OSVSUSE-SU-2026:24139-1 No score
Security update for python-oauthlib
This update for python-oauthlib fixes the following issues:
- CVE-2026-49264: Oauthlib : Unsafe JSONP callback injection in RevocationEndpoint allows arbitrary JavaScript response generation (bsc#1283526).
- CVE-2026-49265: Oauthlib: Timing Attack Vulnerability in PKCE code_verifier Comparison (bsc#1283527).
- Record
SUSE-SU-2026:24139-1- Updated
- 2026-11-02
OSVSUSE-SU-2026:24189-1 No score
Security update for python-oauthlib
This update for python-oauthlib fixes the following issues:
- CVE-2026-49264: Oauthlib : Unsafe JSONP callback injection in RevocationEndpoint allows arbitrary JavaScript response generation (bsc#1283526).
- CVE-2026-49265: Oauthlib: Timing Attack Vulnerability in PKCE code_verifier Comparison (bsc#1283527).
- Record
SUSE-SU-2026:24189-1- Updated
- 2026-11-02
OSVSUSE-SU-2026:24246-1 No score
Security update for python-oauthlib
This update for python-oauthlib fixes the following issues:
- CVE-2026-49264: Oauthlib : Unsafe JSONP callback injection in RevocationEndpoint allows arbitrary JavaScript response generation (bsc#1283526).
- CVE-2026-49265: Oauthlib: Timing Attack Vulnerability in PKCE code_verifier Comparison (bsc#1283527).
- Record
SUSE-SU-2026:24246-1- Updated
- 2026-11-02
OSVSUSE-SU-2026:4810-1 No score
Security update for python-oauthlib
This update for python-oauthlib fixes the following issues:
- CVE-2026-49264: Oauthlib : Unsafe JSONP callback injection in RevocationEndpoint allows arbitrary JavaScript response generation (bsc#1283526).
- CVE-2026-49265: Oauthlib: Timing Attack Vulnerability in PKCE code_verifier Comparison (bsc#1283527).
- Record
SUSE-SU-2026:4810-1- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
oauthlibPyPI |
3.0.0 up to 4.0.0 | 4.0.0 |
python-oauthlibAzure Linux:3 |
before 3.2.2-4 | 3.2.2-4 |
python-oauthlibDebian:12 |
All versions, plus listed versions 3.2.2-13.2.2-23.2.2-33.2.2-43.3.1-13.3.1-2 |
None known |
python-oauthlibDebian:13 |
All versions, plus listed versions 3.2.2-33.2.2-43.3.1-13.3.1-2 |
None known |
python-oauthlibDebian:14 |
All versions, plus listed versions 3.2.2-33.2.2-43.3.1-13.3.1-2 |
None known |
oauthlibPyPI |
3.0.0 up to 4.0.0, plus listed versions 3.0.13.0.23.1.03.1.13.2.0 Show 4 moreShow less3.2.13.2.23.3.03.3.1 |
4.0.0 |
python-oauthlibSUSE:Linux Micro 6.0 From an advisory covering 2 CVEs |
before 3.2.2-159998.1.1 | 3.2.2-159998.1.1 |
python-oauthlibSUSE:Linux Micro 6.2 From an advisory covering 2 CVEs |
before 3.2.2-160000.3.1 | 3.2.2-160000.3.1 |
python-oauthlibSUSE:Linux Enterprise Server 16.0 From an advisory covering 2 CVEs |
before 3.2.2-160000.3.1 | 3.2.2-160000.3.1 |
python-oauthlibSUSE:Linux Enterprise Server for SAP applications 16.0 From an advisory covering 2 CVEs |
before 3.2.2-160000.3.1 | 3.2.2-160000.3.1 |
Show 10 moreShow less
| Package | Affected | Fixed |
|---|---|---|
python-oauthlibSUSE:Linux Enterprise Module for Public Cloud 15 SP4 From an advisory covering 2 CVEs |
before 3.2.2-150400.12.10.1 | 3.2.2-150400.12.10.1 |
python-oauthlibSUSE:Linux Enterprise Module for Python 3 15 SP7 From an advisory covering 2 CVEs |
before 3.2.2-150400.12.10.1 | 3.2.2-150400.12.10.1 |
python-oauthlibUbuntu:16.04:LTS |
All versions, plus listed versions 1.0.0-11.0.3-1 |
None known |
python-oauthlibUbuntu:18.04:LTS |
All versions, plus listed versions 2.0.1-12.0.4-12.0.6-1 |
None known |
python-oauthlibUbuntu:20.04:LTS |
All versions, plus listed versions 2.1.0-13.1.0-1ubuntu13.1.0-1ubuntu2 |
None known |
python-oauthlibUbuntu:22.04:LTS |
All versions, plus listed versions 3.1.0-23.1.1-13.2.0-13.2.0-1ubuntu0.1 |
None known |
python-oauthlibUbuntu:24.04:LTS |
All versions, plus listed versions 3.2.2-1 |
None known |
python-oauthlibUbuntu:26.10 |
All versions, plus listed versions 3.3.1-1build13.3.1-2 |
None known |
python-oauthlibUbuntu:26.04:LTS |
All versions, plus listed versions 3.2.2-33.3.1-13.3.1-1build1 |
None known |
python-oauthlibopenSUSE:Leap 16.0 From an advisory covering 2 CVEs |
before 3.2.2-160000.3.1 | 3.2.2-160000.3.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected | OSV | |
| affected | ||
| facts | OSV | |
| affected, aliases, references | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-49265 is a medium vulnerability (CVSS 6.8) in Oauthlib, published September 29, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.24%, the 15th percentile. Fixed in oauthlib 4.0.0.
References
github.com/oauthlib/oauthlib/security/advisories/GHSA-xpv3-w29h-x7cv
github.com/oauthlib/oauthlib/pull/963
github.com/oauthlib/oauthlib/commit/74664d3fe037a354e180e305135c6bab1747a6b0
github.com/oauthlib/oauthlib/releases/tag/v4.0.0
github.com/pypa/advisory-database/tree/main/vulns/oauthlib/PYSEC-2026-4114.yaml
github.com/oauthlib/oauthlib/commit/40b0ab56da3682c2484a4b78bbff309f8025d950
Show 16 moreShow less
nvd.nist.gov/vuln/detail/CVE-2026-49265
github.com/advisories/GHSA-xpv3-w29h-x7cv
github.com/CVEProject/cvelistV5/tree/main/cves/2026/49xxx/CVE-2026-49265.json
security-tracker.debian.org/tracker/CVE-2026-49265
github.com/oauthlib/oauthlib
pypi.org/project/oauthlib
suse.com/support/update/announcement/2026/suse-su-202624139-1
bugzilla.suse.com/1283526
bugzilla.suse.com/1283527
suse.com/security/cve/CVE-2026-49264
suse.com/security/cve/CVE-2026-49265
suse.com/support/update/announcement/2026/suse-su-202624189-1
suse.com/support/update/announcement/2026/suse-su-202624246-1
suse.com/support/update/announcement/2026/suse-su-20264810-1
ubuntu.com/security/CVE-2026-49265
cve.org/CVERecord?id=CVE-2026-49265