From 3cb774a5cdd89a47117423cfd9030b4b0742795a Mon Sep 17 00:00:00 2001 From: Colby McHenry Date: Sat, 1 Aug 2026 16:48:24 -0500 Subject: [PATCH] =?UTF-8?q?fix(telemetry-dashboard):=20accept=20Origin:=20?= =?UTF-8?q?null=20on=20login=20=E2=80=94=20our=20own=20no-referrer=20polic?= =?UTF-8?q?y=20locked=20Chromium=20out=20(CG-16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dashboard sends Referrer-Policy: no-referrer, and Chromium's behavior on a same-origin form submit from such a page is to send Origin: null. isSameOriginPost() fed "null" to new URL(), which throws → false → 400 "bad request" for every Chromium user typing the correct password. Treat a null Origin like an absent one: it is an unattributed origin, not a foreign one — curl (no Origin at all) was always allowed, the login POST carries no session to ride, and the password is the credential. Real foreign origins stay rejected. The regression net now posts the way Chromium actually does: the smoke-auth sign-in and logout carry Origin: null, and cross-origin logout gets its own rejection case (54 → 56 assertions). The suites missed this because every passing login came from curl or Node fetch — neither sends an Origin header — while render-check injects its cookie past the form. Co-Authored-By: Claude Fable 5 --- telemetry-dashboard/scripts/smoke-auth.sh | 14 +++++++++++--- telemetry-dashboard/src/auth.ts | Bin 6473 -> 6888 bytes 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/telemetry-dashboard/scripts/smoke-auth.sh b/telemetry-dashboard/scripts/smoke-auth.sh index e8f0a8c0e..3fe357bae 100755 --- a/telemetry-dashboard/scripts/smoke-auth.sh +++ b/telemetry-dashboard/scripts/smoke-auth.sh @@ -121,8 +121,14 @@ check "cross-origin post → 400" 400 \ "$(status -X POST "$BASE/login" -H 'Origin: https://evil.example' -d "password=${PASSWORD}")" # One sign-in, then every cookie assertion reads the captured headers. Doing a # fresh POST per assertion would burn the login rate limit and 429 halfway down. -SIGNIN="$(curl -s -D - -o /dev/null -c "$JAR" -X POST "$BASE/login" -d "password=${PASSWORD}" -d "next=/")" -check "correct password → 302" "302" "$(printf '%s' "$SIGNIN" | head -1 | awk '{print $2}')" +# The sign-in carries `Origin: null` — what Chromium actually sends on a +# same-origin form submit from a page with our `Referrer-Policy: no-referrer` +# header. Rejecting it locked every Chromium browser out of the login form +# while curl-shaped tests (no Origin at all) kept passing. +SIGNIN="$(curl -s -D - -o /dev/null -c "$JAR" -X POST "$BASE/login" -H 'Origin: null' -d "password=${PASSWORD}" -d "next=/")" +SIGNIN_STATUS="$(printf '%s' "$SIGNIN" | head -1 | awk '{print $2}')" +check "correct password → 302" "302" "$SIGNIN_STATUS" +check "Origin: null (Chromium form post) not rejected" "yes" "$([ "$SIGNIN_STATUS" != "400" ] && echo yes || echo no)" contains "cookie is HttpOnly" "HttpOnly" "$SIGNIN" contains "cookie is Secure" "Secure" "$SIGNIN" contains "cookie is SameSite=Lax" "SameSite=Lax" "$SIGNIN" @@ -173,10 +179,12 @@ check "tampered cookie on a page → 302 to login" 302 \ echo echo "Sign-out" -check "POST /logout → 302" 302 "$(status -X POST "$BASE/logout")" +check "POST /logout → 302" 302 "$(status -X POST "$BASE/logout" -H 'Origin: null')" contains "logout clears the cookie" "Max-Age=0" \ "$(curl -s -D - -o /dev/null -X POST "$BASE/logout")" check "GET /logout → 405" 405 "$(status "$BASE/logout")" +check "cross-origin logout → 400" 400 \ + "$(status -X POST "$BASE/logout" -H 'Origin: https://evil.example')" echo echo "Rate limiting (6 attempts in a minute; the 6th should be capped)" diff --git a/telemetry-dashboard/src/auth.ts b/telemetry-dashboard/src/auth.ts index 6c1a50f903a5588eff3d735180e029094a10ccae..bf8e5eba46a10857d4a9d610a3ef1f617c09854f 100644 GIT binary patch delta 427 zcmXw$Jx;?w5Jr1Wkd9HBfRrBzi6+PeLX=1dI6&6+*dDyuiDqZ9QiVIfLAVBoKtfa; zgE4j*7wh@nzHj#P;`j37dvaKcJ5Q=kZ4;}mWh;Vq>tL=0sF4&dPN`tEkYLNx`b zSnOZQx1<)p0NNnzT#Y9HMk|~Mq2-bQcL6pJSfL2Y;+{Pf`!xh!$auCnK!dJCfuGlR zZ~;)cXmB6c}a9n1=s@FZxyrs1i@KJ9XI))Bb|!DlR#LTxhx%yZF3 zz!#ML(DTq2P0<86DRA{)#`Ce~+!~S}*s88*ZLn*2fVF|UIJS?mV<{o@X!~M`rP=0U s6Lw%*>z7oKM1`Gq1uhLi6`Y-pOU<$jX8k+N&P`jBSV9tBy?ssmA9Pri)&Kwi delta 11 ScmaE1deUga1BuD?QkeiFqy<(0