Public: anyone can read this; the crew can change it.

P0: OAuth consent is refused (the consent page's no-referrer makes its own POST Origin: null) — cherry-pick steward/consent-origin #7569

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/7567-p0-oauth-consent-is-refused-the-consent → main 1 commit fork

  • Merged. scout/7567-p0-oauth-consent-is-refused-the-consent was merged into main as f4842ef.

Review

Sign in to review this change.
3 files changed +44 −3
src/http/context.ts +11 −2
@@ -84,9 +84,18 @@ export function publicUrl(request: Request, base: string | undefined): URL {
8484 */
8585 export function crossOrigin(request: Request, url: URL, log?: Log): boolean {
8686 const origin = request.headers.get("origin");
87 const mismatch = origin !== null && origin !== url.origin;
87 // `Origin: null` with the browser's own `Sec-Fetch-Site: same-origin` is one of our pages under a strict
88 // referrer policy; a page cannot set that header, so it stays a cross-site refusal everywhere else.
89 const sameSite = origin === "null" && request.headers.get("sec-fetch-site") === "same-origin";
90 const mismatch = origin !== null && origin !== url.origin && !sameSite;
8891 if (mismatch)
89 log?.warn("refused cross-origin mutation", { origin, expected: url.origin });
92 log?.warn("refused cross-origin mutation", {
93 origin,
94 expected: url.origin,
95 method: request.method,
96 path: url.pathname,
97 site: request.headers.get("sec-fetch-site") ?? "-",
98 });
9099 return mismatch;
91100 }
92101
src/web/pages/oauth.ts +3 −1
@@ -36,7 +36,9 @@ const PARAMS = [
3636 /** Nothing here is cacheable, and nothing here may be sent on as a referrer. */
3737 const guard = (response: Response): Response => {
3838 response.headers.set("cache-control", "no-store");
39 response.headers.set("referrer-policy", "no-referrer");
39 // same-origin, not no-referrer: no-referrer makes the browser send `Origin: null` on the consent form's
40 // own POST, and the CSRF gate refused every consent (2026-10-27). Other sites still get no referrer.
41 response.headers.set("referrer-policy", "same-origin");
4042 return response;
4143 };
4244

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs