Summary
The SDK builds its default httpx client with follow_redirects=True (src/openai/_base_client.py:838) and does not strip any headers of its own on redirect. httpx's cross-origin redirect protection removes Authorization (and Cookie) when the origin changes, but it does not remove custom headers. The Azure integration authenticates with a custom api-key header (src/openai/lib/azure.py), so on a cross-origin redirect the Azure api-key is forwarded to the new origin, while an Authorization: Bearer credential in the same position would be stripped.
This is a defense-in-depth gap rather than a leak that fires in normal operation: the Azure OpenAI data-plane returns JSON, not cross-origin redirects, so a redirect has to be introduced by a gateway/proxy in front of the endpoint or by a malicious/compromised host. But the asymmetry (a sensitive auth header that survives a cross-origin redirect where Authorization would not) is worth closing.
Reproduction
Confirmed on openai==2.46.0 with httpx==0.28.1.
import httpx
# host A responds 302 -> a DIFFERENT origin (host B); host B records what it received.
with httpx.Client(follow_redirects=True) as c:
c.get("http://host-a/v1/models",
headers={"Authorization": "Bearer CANARY", "api-key": "CANARY-APIKEY"})
# host B receives:
# Authorization : None <- httpx stripped it (cross-origin protection)
# api-key : CANARY-APIKEY <- forwarded to the other origin
The same holds through the real client: AzureOpenAI(api_key=..., azure_endpoint="http://host-a") following a cross-origin 302 delivers the api-key to host B.
Why the two headers differ
httpx's redirect logic only knows the standard credential headers (Authorization, Cookie). The Azure overlay authenticates with api-key, which httpx does not recognize as sensitive, so it rides along on cross-origin redirects.
Related
This is the redirect-path sibling of the unconditional Azure credential issue fixed in openai/openai-go#698 (first-party bearer sent to the Azure host). That one was addressed at the overlay; this one is about custom auth headers surviving a cross-origin redirect, which is a slightly different code path.
Suggested fix
Any one of the following closes it:
- On a cross-origin redirect, strip the SDK's own sensitive headers (e.g.
api-key) in addition to whatever httpx already removes, mirroring httpx's Authorization/Cookie handling for custom auth headers.
- Default the SDK's httpx client to
follow_redirects=False (the API does not rely on redirects), or scope redirect-following to same-origin.
- Add a regression test asserting that
api-key is absent on a cross-origin redirect target, alongside the existing Azure auth tests.
More generally, an SDK that authenticates via a non-Authorization header while following redirects should treat that header as redirect-sensitive.
Summary
The SDK builds its default httpx client with
follow_redirects=True(src/openai/_base_client.py:838) and does not strip any headers of its own on redirect. httpx's cross-origin redirect protection removesAuthorization(andCookie) when the origin changes, but it does not remove custom headers. The Azure integration authenticates with a customapi-keyheader (src/openai/lib/azure.py), so on a cross-origin redirect the Azureapi-keyis forwarded to the new origin, while anAuthorization: Bearercredential in the same position would be stripped.This is a defense-in-depth gap rather than a leak that fires in normal operation: the Azure OpenAI data-plane returns JSON, not cross-origin redirects, so a redirect has to be introduced by a gateway/proxy in front of the endpoint or by a malicious/compromised host. But the asymmetry (a sensitive auth header that survives a cross-origin redirect where
Authorizationwould not) is worth closing.Reproduction
Confirmed on
openai==2.46.0withhttpx==0.28.1.The same holds through the real client:
AzureOpenAI(api_key=..., azure_endpoint="http://host-a")following a cross-origin 302 delivers theapi-keyto host B.Why the two headers differ
httpx's redirect logic only knows the standard credential headers (
Authorization,Cookie). The Azure overlay authenticates withapi-key, which httpx does not recognize as sensitive, so it rides along on cross-origin redirects.Related
This is the redirect-path sibling of the unconditional Azure credential issue fixed in openai/openai-go#698 (first-party bearer sent to the Azure host). That one was addressed at the overlay; this one is about custom auth headers surviving a cross-origin redirect, which is a slightly different code path.
Suggested fix
Any one of the following closes it:
api-key) in addition to whatever httpx already removes, mirroring httpx'sAuthorization/Cookiehandling for custom auth headers.follow_redirects=False(the API does not rely on redirects), or scope redirect-following to same-origin.api-keyis absent on a cross-origin redirect target, alongside the existing Azure auth tests.More generally, an SDK that authenticates via a non-
Authorizationheader while following redirects should treat that header as redirect-sensitive.