Apache Airflow Provider(s)
http
What happened
HttpAsyncHook.config copies every non-reserved key of an HTTP Connection's extra field into the aiohttp.ClientSession headers, and the provider docs endorse that field as a place to carry credentials ("Login and Password authentication can be used along with any authentication method using headers. Headers can be given in json format in the Extras field").
aiohttp follows redirects by default and strips only the literal Authorization header when the redirect changes host. A secret carried under any other header name (X-API-Key, Private-Token, apikey, ...) is a plain session header and is replayed verbatim to every host in the redirect chain. Verified against aiohttp 3.14.1: Authorization is dropped on a cross-host redirect, X-API-Key is forwarded.
The destination does not have to be attacker-controlled for this to leak - an API that 302s downloads to a CDN or object store receives the connection's key.
What you think should happen instead
Connection-supplied headers should get the same treatment aiohttp already gives Authorization: dropped once the redirect leaves the original host, preserved on same-host redirects.
Follow-up work
#70000 fixes the synchronous HttpHook by subclassing requests.Session and extending rebuild_auth, which is the hook requests exposes for exactly this. aiohttp has no equivalent per-redirect callback, so the async side needs a different approach - most likely disabling automatic redirect following in HttpAsyncHook.run and walking the chain manually so headers can be recomputed per hop, or moving the connection headers off the session and onto each request.
Acceptance criteria
- A cross-host redirect from
HttpAsyncHook does not forward Connection extra headers.
- A same-host redirect still forwards them.
- Regression test covering both directions, mirroring
test_connection_header_is_only_forwarded_on_a_same_host_redirect in providers/http/tests/unit/http/hooks/test_http.py.
Are you willing to submit PR?
Apache Airflow Provider(s)
http
What happened
HttpAsyncHook.configcopies every non-reserved key of an HTTP Connection'sextrafield into theaiohttp.ClientSessionheaders, and the provider docs endorse that field as a place to carry credentials ("Login and Password authentication can be used along with any authentication method using headers. Headers can be given in json format in the Extras field").aiohttpfollows redirects by default and strips only the literalAuthorizationheader when the redirect changes host. A secret carried under any other header name (X-API-Key,Private-Token,apikey, ...) is a plain session header and is replayed verbatim to every host in the redirect chain. Verified against aiohttp 3.14.1:Authorizationis dropped on a cross-host redirect,X-API-Keyis forwarded.The destination does not have to be attacker-controlled for this to leak - an API that 302s downloads to a CDN or object store receives the connection's key.
What you think should happen instead
Connection-supplied headers should get the same treatment
aiohttpalready givesAuthorization: dropped once the redirect leaves the original host, preserved on same-host redirects.Follow-up work
#70000 fixes the synchronous
HttpHookby subclassingrequests.Sessionand extendingrebuild_auth, which is the hookrequestsexposes for exactly this.aiohttphas no equivalent per-redirect callback, so the async side needs a different approach - most likely disabling automatic redirect following inHttpAsyncHook.runand walking the chain manually so headers can be recomputed per hop, or moving the connection headers off the session and onto each request.Acceptance criteria
HttpAsyncHookdoes not forward Connectionextraheaders.test_connection_header_is_only_forwarded_on_a_same_host_redirectinproviders/http/tests/unit/http/hooks/test_http.py.Are you willing to submit PR?