PT-2026-105863 · Pypi · Oauthlib

Published

2026-10-01

·

Updated

2026-10-01

CVSS v3.1

6.8

Medium

VectorAV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N

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

Fix

Found an issue in the description? Have something to add? Feel free to write us 👾

Related Identifiers

PYSEC-2026-4114

Affected Products

Oauthlib