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
Affected software
Click a technology to see all vulnerabilities affecting it.
| Platform | Package | Vulnerable versions | Fixed in |
|---|---|---|---|
| Python (PyPI) | oauthlib | >= 3.0.0, < 4.0.0 | 4.0.0 |
References
- https://github.com/oauthlib/oauthlib/security/advisories/GHSA-xpv3-w29h-x7cv
- https://github.com/oauthlib/oauthlib/pull/963
- https://github.com/oauthlib/oauthlib/commit/40b0ab56da3682c2484a4b78bbff309f8025d950
- https://github.com/oauthlib/oauthlib
- https://pypi.org/project/oauthlib
- https://github.com/advisories/GHSA-xpv3-w29h-x7cv
- https://nvd.nist.gov/vuln/detail/CVE-2026-49265
- https://github.com/pypa/advisory-database/tree/main/vulns/oauthlib/PYSEC-2026-4114.yaml
- CVSS vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N- Weakness (CWE)
CWE-208- Platform
- Python (PyPI)
- Package
oauthlib- Disclosed
- 29.09.2026
- Updated
- 13.10.2026 18:17
Sources and licenses
OSV / GitHub Advisory Database - PYSEC-2026-4114 - PyPA Advisory Database; CC BY 4.0
OSV / GitHub Advisory Database - GHSA-xpv3-w29h-x7cv - CC BY 4.0
Vulnerability history: oauthlib
All published vulnerabilities of this package (Python (PyPI)), newest first. Shows whether this is a one-off slip or a package that needs watching.
- Total entries
- 3
- First → latest
- 09.2022 09.2026
- Without a fix
- 0
- Exploited in attacks
- 0
Severity breakdown
- Medium 3
Disclosures per year
- 2022: 1
- 2023: 0
- 2024: 0
- 2025: 0
- 2026: 2
-
Oauthlib: Timing Attack Vulnerability in PKCE code_verifier Comparison (CWE-208) this entry
Know which vulnerabilities affect your application
With the DockRay integration and software inventory enabled, DockRay checks reported component versions against known vulnerabilities and notifies you about confirmed matches. Coverage depends on the supported technology and available advisory data.