Repository navigation
fix(server): HTML renders and PDFs load behind a proxy that forbids framing - #28
Conversation
… group (pingdotgg#16353) Fixes pingdotgg#4880. Originally pingdotgg#14639 by @Project516. Co-authored-by: Project516 <138796702+Project516@users.noreply.github.com>
…ingdotgg#13758) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…14718) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…16357) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…dotgg#16206) Favicons in ProjectEnrichmentService now keep for 15 minutes. Repository identity keeps its 1-minute TTL, so remote changes still show within a minute. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… histories (pingdotgg#16358) The Claude capabilities probe now asks for usage with skipBehaviors, so it no longer scans every local transcript and misses its 4 s deadline. Takes over pingdotgg#14456. Co-authored-by: Ashkaan <a@ashkaan.me>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tgg#16285) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…otgg#16223) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ingdotgg#16207) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ingdotgg#16315) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…gain (pingdotgg#16363) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ingdotgg#16314) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…g#16253) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ingdotgg#16382) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…g#9786) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…#9788) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…#10298) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…rver (pingdotgg#16718) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…g#16741) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…16752) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ngdotgg#16290) Co-authored-by: spoukyii <61633921+spoukyii@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ices (pingdotgg#16631) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tgg#16762) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s of untracked files (pingdotgg#16771) Co-authored-by: Braulio Oliveira <brauliobo@gmail.com> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
…eep (pingdotgg#16760) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ingdotgg#16761) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ingdotgg#16782) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brings in 109 upstream commits (GitHub API transport, MCP OAuth for outside agents, split auth scopes, server-side preview browser, status polling fixes). Fork adjustments: - Side-chat RPCs keep their orchestration scopes beside upstream's split scopes and are listed in the new RPC instrumentation table; their handlers drop the removed observeRpc* wrappers. - Side-chat composer passes the new canOperateThread prop. - The SQLite client binds booleans as 0/1: upstream's pairing query binds a boolean, which Node 24.16 (the service runtime) rejects. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Upstream now pins overrides such as undici@^8 to the catalog; the packaging script looked up the whole selector and failed. Mirrors upstream pingdotgg#16411. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…raming Clients frame asset documents from the environment's origin, which is often not their own. A reverse proxy that adds X-Frame-Options: SAMEORIGIN blanked every HTML render and PDF preview in that setup. Inline HTML and PDF asset responses now carry `frame-ancestors *`, which browsers honour in place of X-Frame-Options. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9df3ee01cd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // Clients frame documents from another origin than the environment's, so name | ||
| // the allowed ancestors here: a browser that sees `frame-ancestors` ignores any | ||
| // `X-Frame-Options` a reverse proxy adds. The signed URL is the access control. | ||
| const FRAMEABLE_CONTENT_SECURITY_POLICY = "frame-ancestors *"; |
There was a problem hiding this comment.
Allow the desktop schemes as frame ancestors
In the desktop client, the parent document uses the custom t3code://app or t3code-dev://app origin, while signed asset URLs are resolved against the environment's HTTP base URL. CSP's * source matches HTTP(S) ancestors or ancestors using the protected resource's scheme, so it does not match either desktop scheme. Consequently, this newly enforced policy blocks every HTML and PDF iframe in desktop, even without a reverse proxy; include the two desktop schemes explicitly in the frame-ancestors list.
AGENTS.md reference: AGENTS.md:L23-L31
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Real: CSP's * does not match the desktop renderer's custom-scheme origins, so this would have blanked HTML and PDF frames in desktop. Fixed in 0a35443 by listing t3code://app and t3code-dev://app alongside *.
CSP's `*` matches only http(s) ancestors, so the desktop app's custom scheme origins are listed explicitly. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Summary
A client on one host (
dev.…) frames asset documents served by the environment on another (code.…). The gateway in front of the environment addsX-Frame-Options: SAMEORIGIN, so every in-thread HTML render and PDF preview came up blank. Browsers ignoreX-Frame-Optionswhen the response names its ownframe-ancestors, so the server now does.Downloads, SVGs, media and the app shell are unchanged.
Evidence
curl -I https://code.andrei-homelab.com/showsx-frame-options: SAMEORIGINfrom nginx and noframe-ancestorson asset documents, so the cross-origin frame is refused.After:
vp test run apps/server/src/http.test.tspasses (28 tests), asserting the new header on HTML by mime type, HTML by path, PDF by mime type and PDF by path.Merge Danger
Door: two-way
Reverting the commit restores the old headers; nothing is persisted.
Blast Radius: small
Asset documents had no framing restriction from the server before, so this only matters where a proxy imposed one. Those documents can now be framed by any site that holds the signed, expiring URL; HTML stays sandboxed to an opaque origin.
Claude Opus 5.5 (1M context) via Claude Code in T3 Code
🤖 Generated with Claude Code