GHSA-xpv3-w29h-x7cv
Oauthlib: Timing Attack Vulnerability in PKCE code_verifier Comparison (CWE-208)
Packages
Details
As written in the advisory (Markdown source, shown as plain text).
## 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):
| 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
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
References
External links from the advisory. They lead to third-party sites.
- https://github.com/oauthlib/oauthlib/security/advisories/GHSA-xpv3-w29h-x7cv
- https://nvd.nist.gov/vuln/detail/CVE-2026-49265
- https://github.com/oauthlib/oauthlib/pull/963
- https://github.com/oauthlib/oauthlib/commit/40b0ab56da3682c2484a4b78bbff309f8025d950
- https://github.com/oauthlib/oauthlib
- https://github.com/pypa/advisory-database/tree/main/vulns/oauthlib/PYSEC-2026-4114.yaml