HexBrain

curl · Report #3595753

Connection Reuse Ignores OAuth Bearer Token Mismatch

N/Astatus
mediumseverity
17upvotes
10 Mar 2026disclosed

How it was found

Summary:

The connection pool reuse function url_match_conn() in lib/url.c checks oauth_bearer in its credential match block — but only for protocols marked as requiring per-connection credentials. For HTTP, OAuth bearer is passed as a header, not a protocol-level credential. If a libcurl application reuses an easy handle to connect to two different API endpoints using different bearer tokens without setting CURLOPT_FRESH_CONNECT=1, the connection pool may serve the second request on the first connection, attaching the WRONG bearer token. This is closely related to the class of bugs that produced CVE-2022-22576 (OAuth2 bearer bypass in connection reuse).

Affected version

Identified in current master

Steps To Reproduce:

Multi-tenant API server using a shared libcurl instance (common in thread pools, connection-pooling proxies, Go/Python/Java bindings):

  1. User attacker1 authenticates → curl makes HTTP request with CURLOPT_XOAUTH2_BEARER = token_attacker1 → TCP connection opened to api.example.com:443 → conn->oauth_bearer = token_alice → Connection returned to pool (keep-alive)

  2. User attacker2 makes a request to the SAME host → curl sets CURLOPT_XOAUTH2_BEARER = token_attacker2 on easy handle → url_match_conn() finds Alice's connection in pool → oauth_bearer check is SKIPPED (PROTOPT_CREDSPERREQUEST gate) → attacker2's connection is reused → lib/http.c builds: Authorization: Bearer token_alice ← BUG → API server receives attacker2's request authenticated as Alice → attacker2 receives attacker1's data / can take attacker2's actions

python3 poc_bearer_reuse.py

Impact

impact:

Requests to different APIs on the same host may share a persistent HTTP connection, causing the wrong OAuth bearer token to be used. In multi-tenant applications (serving different users from the same libcurl instance) this can lead to cross-account credential leakage and unauthorized API access.

recommended

Set CURLOPT_FRESH_CONNECT=1 when switching bearer tokens between requests on the same host. Application-level fix: call curl_easy_reset() or create a new easy handle per token boundary. Structural fix: ensure oauth_bearer changes force connection pool expiry for HTTP connections regardless of per-connection credential flag.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original