Repository navigation
Conversation
f7f5403 to
fcd94e8
Compare
|
🤖 Review pass on this branch, run by an agent on Rosa's account. Two commits pushed on top of yours; everything else below is left for you to decide. Base branch
Retargeting to Credentials on a redirect, every hopWith
Hostile Pushed
Worth deciding before merge1. Multi-hop is the regression to weigh. 2. 3. The origin comparison widens behaviour as well as tightening it. 4. Nits. An empty 5. The description and commit message describe the pre-#211 code ("attached the WebView's cookies as a static Cookie header and issued the request with a redirect-following client"). On this base that isn't what the fetch does any more. I left your commit message alone. 6. #215 overlaps. It adds One nice side effect nobody claimed: |
|
Thanks, looks good but I'll re-build the changes on #215 when it's merged. |
The native redirect-verification fetch attached the WebView's cookies as a static Cookie header and issued the request with a redirect-following client. On a cross-origin redirect, OkHttp forwards that caller-set Cookie header to the destination (it drops Authorization on a host change, but not a caller-set Cookie), delivering first-party cookies to a different origin. The fetch only needs to detect a cross-origin redirect, not follow it with credentials. Disable redirect following on the verification client and resolve the destination from the Location header, comparing the full origin (scheme, host, and port) so a scheme downgrade or port change counts as cross-origin. No credential-bearing request is ever sent to a redirect destination. Session.visitRequestFailedWithNonHttpStatusCode no longer gates on response.isSuccessful (which only held when redirects were followed to a 2xx); detecting the cross-origin redirect response is sufficient to propose the cross-origin redirect visit. Adds HttpRepositoryTest (MockWebServer) covering the no-leak invariant, cross/same-origin detection, and relative Location resolution.
Keep the reason the fetch doesn't follow redirects and drop the rest: the same-origin comparison reads off its own body, and the guarantee it supports is stated once where the client is built. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DyPGJuffiyfWW9113PNxHG
Both MockWebServer instances bind the same loopback host, so the existing cross-origin case differs from the first-party origin only by port and exercises just the port term of the origin comparison. Add a case with an absolute off-host Location, which needs no second server precisely because the redirect isn't followed. Also trim the test's comments, keeping the two that say why a request count is asserted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DyPGJuffiyfWW9113PNxHG
Use the shared origin comparison from the trust policy instead of a private HttpUrl extension. Both compare scheme, host, and effective port, and an HttpUrl is always http(s), so the result is unchanged.
7791f59 to
d2e3ff8
Compare
The response was never closed, so a redirect with a body kept its connection out of the pool. Session no longer reads the response now that the fetch doesn't follow redirects, so return the redirect and close the response with use.
The timeouts can't change, and a lazily built client would also see the cache. What an eager field would miss is the caching client Session installs after constructing this repository.
Summary
The native redirect-verification fetch in
HttpRepositoryattaches the WebView's cookies to the request as a staticCookieheader and then issues it with a client that follows redirects. When the requested URL responds with a cross-origin redirect, OkHttp forwards that manually-setCookieheader to the redirect destination — delivering first-party session cookies to a different origin. (OkHttp drops theAuthorizationheader when a redirect changes host, but it does not drop a caller-setCookieheader.)This fetch only needs to detect whether the response is a cross-origin redirect; it never needs to follow that redirect with credentials. This change stops following redirects on the verification fetch and inspects the
Locationheader directly, so no credential-bearing request is ever sent to a redirect destination.Changes
followRedirects(false)/followSslRedirects(false).Location. The redirect target is computed by resolving theLocationheader against the request URL, so relative, protocol-relative, and absolute locations are all handled correctly.Session.visitRequestFailedWithNonHttpStatusCodepreviously gated onresponse.isSuccessful, which only held when redirects were followed through to a 2xx. Since the verification fetch no longer follows redirects, the response is the unfollowed 3xx; detecting a cross-origin redirect is now sufficient to propose the cross-origin redirect visit.Only the first redirect hop is inspected — sufficient to detect a direct cross-origin redirect. Deeper same-origin chains that would eventually cross origin now fail closed (the visit fails) rather than being followed with credentials.
Testing
Adds
HttpRepositoryTest(MockWebServer):Cookieor other credential can reach it — while the first-party request still carries its cookies.Locationresolves against the request origin (same-origin).Scope run locally:
./gradlew :core:testDebugUnitTest(core module unit tests).