Skip to content

fix(liveview): SameSite=None on live cookie so the cross-site iframe sends it - #408

Merged
jrothrock merged 1 commit into
mainfrom
fix/live-cookie-samesite-none
Sep 8, 2026
Merged

jrothrock merged 1 commit into
mainfrom
fix/live-cookie-samesite-none

Conversation

@jrothrock

Copy link
Copy Markdown
Collaborator

The bug

Live View showed a white screen even after the frame-ancestors CSP fix (#407). Root cause is a second cross-origin problem underneath the CSP one: the live-auth cookie was SameSite=Strict.

The iframe's origin is localhost:<livePort> but it is embedded by the dashboard at 127.0.0.1:<dashPort>. Browsers treat localhost and 127.0.0.1 as different sites, so every request the iframe makes is cross-site (third-party). A Strict/Lax cookie is never sent there:

  1. Iframe loads …?__live_token=X → server 302s and sets the Strict cookie.
  2. Browser follows to the clean URL — framed, third-party, no token param → cookie withheld → 403 → white screen.

verify-live-view never caught this: it loads the URL top-level (first-party), where Strict works fine — so it reported rendered: true while the browser stayed white.

The fix

SameSite=None; Secure — the only cookie sent in a cross-site context. Browsers accept Secure cookies over http://localhost as a loopback exception, so it works on plain HTTP.

Not a security regression

SameSite controls when the cookie is sent, not who can read it. The token is single-purpose (authorizes framing the sandbox app, zero dashboard access — dashboard uses a separate corral_dash_token on 127.0.0.1, never sent to localhost). Still HttpOnly (framed app JS can't read it) and host-only loopback. Framing remains gated by the CSP frame-ancestors allowlist (loopback dashboard origins only). The untrusted-app → dashboard barrier is unchanged.

Test TestRequireLiveAuth now asserts SameSite=None; Secure so this can't regress.

🤖 Generated with Claude Code

…s it

The live-auth cookie was SameSite=Strict. The iframe's origin is
localhost:<live> but it's embedded by the dashboard at 127.0.0.1:<dash>;
browsers treat those as different sites, so the framed request is
cross-site and a Strict cookie is never sent. The 302 set the cookie but
the follow-up framed request omitted it -> 403 -> white screen. The
verify-live-view endpoint missed this because it loads the URL top-level
(first-party), where Strict works -> reported rendered:true while the
browser showed white.

Use SameSite=None; Secure (the only cookie sent cross-site; browsers
accept Secure over http://localhost as a loopback exception). No
isolation change: the token only authorizes framing the sandbox app,
never dashboard access; still HttpOnly + host-only loopback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jrothrock
jrothrock merged commit 2facf11 into main Sep 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant