Skip to content

Don't forward credentials when the verification fetch encounters a cross-origin redirect - #213

Open
jeremy wants to merge 1 commit into
host-scoped-webview-cookiesfrom
security/verification-fetch-no-credential-redirect
Open

Don't forward credentials when the verification fetch encounters a cross-origin redirect#213
jeremy wants to merge 1 commit into
host-scoped-webview-cookiesfrom
security/verification-fetch-no-credential-redirect

Conversation

@jeremy

@jeremy jeremy commented Aug 26, 2026

Copy link
Copy Markdown
Member

Summary

The native redirect-verification fetch in HttpRepository attaches the WebView's cookies to the request as a static Cookie header and then issues it with a client that follows redirects. When the requested URL responds with a cross-origin redirect, OkHttp forwards that manually-set Cookie header to the redirect destination — delivering first-party session cookies to a different origin. (OkHttp drops the Authorization header when a redirect changes host, but it does not drop a caller-set Cookie header.)

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 Location header directly, so no credential-bearing request is ever sent to a redirect destination.

Changes

  • Don't follow redirects on the verification fetch. Its client is now derived from the shared client (keeping its cache, timeouts, and interceptors) with followRedirects(false) / followSslRedirects(false).
  • Resolve the destination from Location. The redirect target is computed by resolving the Location header against the request URL, so relative, protocol-relative, and absolute locations are all handled correctly.
  • Compare full origin, not just host. A redirect is treated as cross-origin when scheme, host, or port differ — so an HTTPS→HTTP downgrade or a port change is correctly detected as cross-origin.
  • Caller. Session.visitRequestFailedWithNonHttpStatusCode previously gated on response.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):

  • A cross-origin redirect is detected and its destination receives no request at all — so no Cookie or other credential can reach it — while the first-party request still carries its cookies.
  • A same-origin redirect is detected and correctly not flagged cross-origin.
  • A relative Location resolves against the request origin (same-origin).
  • A direct 2xx response reports no redirect.

Scope run locally: ./gradlew :core:testDebugUnitTest (core module unit tests).

@jeremy
jeremy requested review from jayohms and mbarta August 27, 2026 18:33
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.
@jeremy
jeremy changed the base branch from main to host-scoped-webview-cookies August 28, 2026 07:10
@jeremy
jeremy force-pushed the security/verification-fetch-no-credential-redirect branch from f7f5403 to fcd94e8 Compare August 28, 2026 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant