Repository navigation
fix(liveview): white screen — frame-ancestors must name the dashboard origin - #407
Merged
Merged
Conversation
… origin THE white-screen cause. Every verification (the verify-live-view endpoint, and the conductor's exhaustive manual curls) showed the page serves 200 with real content — because they all loaded the URL DIRECTLY, where frame-ancestors never applies. In the actual dashboard it's loaded in a cross-origin IFRAME, and that's where it breaks. The live proxy set `Content-Security-Policy: frame-ancestors 'self'` on the framed app. But the iframe is served from localhost:<livePort> while the dashboard that frames it is 127.0.0.1:<dashPort> — a DIFFERENT origin (browsers treat 127.0.0.1 and localhost as distinct). So 'self' (= the iframe's own origin) did NOT permit the dashboard to frame it → the browser refused the embed → white screen. The separate-origin design was deliberate (keeps the untrusted app off the dashboard origin), but 'self' contradicted it. Name the dashboard's real origins instead: `frame-ancestors http://127.0.0.1:<dashPort> http://localhost:<dashPort>` (both loopback hosts, since either may be how it was opened). Thread the dashboard port (server.dashPort = *port) through to hardenLiveResponse. Security: this is NARROWER than a wildcard, not more open — only the loopback dashboard origins at the specific dashboard port may frame the app; no external site can. The untrusted-app isolation (separate origin, iframe sandbox) is untouched. Verified: isolation test asserts the new CSP names the dashboard origins; live-view/cred/isolation suites green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
THE white-screen root cause
Every verification (the
verify-live-viewendpoint I just shipped, and the conductor's exhaustive manual curls in conv 145) reported the page serves 200 with real content — because they all loaded the URL directly, whereframe-ancestorsnever applies. In the real dashboard the page is loaded in a cross-origin iframe, and that's where it breaks.The live proxy set
Content-Security-Policy: frame-ancestors 'self'on the framed app. But:localhost:<livePort>127.0.0.1:<dashPort>Browsers treat
127.0.0.1andlocalhostas different origins, so'self'(= the iframe's own origin) did not permit the dashboard to frame it → the browser refuses the embed → white screen. (The separate-origin design is deliberate — it keeps the untrusted app off the dashboard's origin — but'self'contradicted it.)Fix
Name the dashboard's real origins:
Both loopback hosts (either may be how the dashboard was opened). Thread the dashboard port (
server.dashPort = *port) through tohardenLiveResponse.Security (asked during review)
This is narrower than a wildcard, not more open — only the loopback dashboard origins at the specific dashboard port may frame the app; no external site can (
'self'was just the wrong single origin). The untrusted-app isolation (separate origin + iframesandbox) is untouched.Verified
The isolation test now asserts the CSP names the dashboard origins; live-view / credential / isolation suites are green. This is the fix that makes Live View actually render in the browser instead of a white screen.
🤖 Generated with Claude Code