Background
This tracks the follow-up discussed during review of #2317 (cross-origin body replay) and #2325 (HTTPS-to-HTTP redirects). We agreed to retain the existing redirect trust model in those PRs and discuss additional restrictions separately.
@hyperxpro, you mentioned opening a separate issue. I am collecting the discussion here together with the related downgrade concern from #2325; happy to consolidate into yours if you have one planned.
Problem
When automatic redirect following is enabled, a body-preserving redirect can forward sensitive request content to another origin or replay it over unencrypted HTTP. Stripping authentication and cookies does not protect information contained in the body itself.
For example, a PUT to an HTTPS upload endpoint could receive a redirect to another host over HTTP. Following that redirect while preserving the request sends the upload to that destination in cleartext.
Because the policy is evaluated per hop, a hostile destination can also chain redirects to receive the body repeatedly, up to maxRedirects.
This capability already existed on 307/308. However, as noted in the #2317 review, an open-redirect endpoint using a helper that defaults to 301/302 can make those statuses easier to exploit: the attacker may control the destination without being able to choose the response status. Existing 307/308 behavior therefore does not make the additional exposure irrelevant.
Any protection should apply consistently across body-preserving redirects, rather than depending on the method, status code or body representation.
Proposed direction
Provide a configurable policy that lets callers refuse cross-origin body replay and HTTPS-to-HTTP redirects before sending the redirected request.
The restriction should refuse the redirect, not silently remove the body while retaining the method. A bodyless PUT, for example, could overwrite the destination resource with empty content.
The JDK provides a useful precedent: HttpClient.Redirect.NORMAL declines HTTPS-to-HTTP redirects and returns the redirect response to the caller. ALWAYS permits those hops, so this is explicitly a policy choice. JDK documentation
Existing method and body-preservation rules should remain applicable to redirects that the policy permits.
Decisions to agree before implementation
- Scope: Should cross-origin body replay and HTTPS downgrades have separate controls? Should downgrade protection also cover requests without bodies?
- Defaults: Should restrictions be opt-in to preserve compatibility, or enabled by default with an explicit opt-out? Legitimate cross-origin upload workflows could be affected by a default change.
- Refusal behavior: Should AHC return the redirect response without following it, or complete the request exceptionally?
- Configuration: Should the policy be configurable both client-wide and per request?
- Composition: How should this interact with
followRedirect and stripAuthorizationOnRedirect? Allowing a redirect should not implicitly authorize forwarding credentials that would otherwise be stripped.
Issue #2178 requests additional control over authorization forwarding. It is related API-design context, although resolving it need not be a prerequisite for this feature.
Whichever policy is chosen should be evaluated on every redirect hop and consistently across supported body representations.
For now, callers can disable automatic redirect following and validate destinations themselves.
AI disclosure
Draft prepared with assistance from OpenAI Codex on behalf of Matthias Kurz.
Background
This tracks the follow-up discussed during review of #2317 (cross-origin body replay) and #2325 (HTTPS-to-HTTP redirects). We agreed to retain the existing redirect trust model in those PRs and discuss additional restrictions separately.
@hyperxpro, you mentioned opening a separate issue. I am collecting the discussion here together with the related downgrade concern from #2325; happy to consolidate into yours if you have one planned.
Problem
When automatic redirect following is enabled, a body-preserving redirect can forward sensitive request content to another origin or replay it over unencrypted HTTP. Stripping authentication and cookies does not protect information contained in the body itself.
For example, a PUT to an HTTPS upload endpoint could receive a redirect to another host over HTTP. Following that redirect while preserving the request sends the upload to that destination in cleartext.
Because the policy is evaluated per hop, a hostile destination can also chain redirects to receive the body repeatedly, up to
maxRedirects.This capability already existed on 307/308. However, as noted in the #2317 review, an open-redirect endpoint using a helper that defaults to 301/302 can make those statuses easier to exploit: the attacker may control the destination without being able to choose the response status. Existing 307/308 behavior therefore does not make the additional exposure irrelevant.
Any protection should apply consistently across body-preserving redirects, rather than depending on the method, status code or body representation.
Proposed direction
Provide a configurable policy that lets callers refuse cross-origin body replay and HTTPS-to-HTTP redirects before sending the redirected request.
The restriction should refuse the redirect, not silently remove the body while retaining the method. A bodyless PUT, for example, could overwrite the destination resource with empty content.
The JDK provides a useful precedent:
HttpClient.Redirect.NORMALdeclines HTTPS-to-HTTP redirects and returns the redirect response to the caller.ALWAYSpermits those hops, so this is explicitly a policy choice. JDK documentationExisting method and body-preservation rules should remain applicable to redirects that the policy permits.
Decisions to agree before implementation
followRedirectandstripAuthorizationOnRedirect? Allowing a redirect should not implicitly authorize forwarding credentials that would otherwise be stripped.Issue #2178 requests additional control over authorization forwarding. It is related API-design context, although resolving it need not be a prerequisite for this feature.
Whichever policy is chosen should be evaluated on every redirect hop and consistently across supported body representations.
For now, callers can disable automatic redirect following and validate destinations themselves.
AI disclosure
Draft prepared with assistance from OpenAI Codex on behalf of Matthias Kurz.