feat(preview): fall back when the site's own CSP blocks the iframe#152
Merged
Conversation
The embedding detection added in v2.0.3 only inspects the target's response headers. That misses the other half of the contract: a target that happily allows framing still renders as an empty box when the embedding site's own CSP frame-src directive does not cover it, and no response header can rescue that. Every preview broken on gethinode.com and demo.gethinode.com failed this way, and the build reported nothing. Check the URL against the frame-src the site itself publishes, and show the fallback with an actionable warning when it is not covered. The published frame-src is the union of what each module contributes through [params.modules.<name>.csp], since the mod-csp baseline declares no frame-src of its own. A site that contributes nothing is not using this CSP system, so nothing can be concluded and the preview renders unchanged. The check runs after the response-header check and only for a target that would otherwise have loaded. Telling an author to add google.com to frame-src would send them after a fix that cannot work, because it refuses to be framed at all. Verified against a local server returning synthetic headers: the 15 existing header cases still produce the correct verdict over both the HEAD and the GET path, and 4 new cases cover the site side — a host allowed by frame-src, 'self', a host absent from frame-src, and a host that the target permits but the site does not. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Author
|
🎉 This PR is included in version 2.1.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
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.
Problem
The embedding detection shipped in v2.0.3 only inspects the target's response headers. That is
one half of the contract. A target that happily permits framing still renders as an empty box
when the embedding site's own CSP
frame-srcdirective does not cover it — and no response headercan rescue that.
This is not hypothetical: it is how every preview bug in the recent round actually failed.
frame-srccovers it?In every case the build was silent. This check makes all five a build warning plus a graceful
screenshot fallback.
Change
Check the URL against the
frame-srcthe site itself publishes, and show the fallback with anactionable warning when it is not covered:
The published
frame-srcis the union of what each module contributes through[params.modules.<name>.csp], since the mod-csp baseline declares noframe-srcof its own. Thisreads the same source of truth mod-csp does, without coupling to its assembly code. A site that
contributes nothing is not using this CSP system, so nothing can be concluded and the preview
renders unchanged — no false positives for non-mod-csp sites.
Ordering
The check runs after the response-header check, and only for a target that would otherwise have
loaded. Running it first would be cheaper (no network request), but it would tell an author to add
google.comtoframe-src— sending them after a fix that cannot work, since google.com refusesto be framed at all. The block reference previews google.com on purpose to demonstrate exactly
that case.
Verification
Against a local server returning synthetic headers:
HEADand theGETpath — no regression.frame-srcset to['*.wikipedia.org', "'self'"]:en.wikipedia.org'self'weareadaptiq.comallow-hostEnd to end on the real hinode exampleSite (via a workspace
use), with mod-docs declaring itssources: Wikipedia and OpenStreetMap render live, google.com falls back, no warnings. Removing
the mod-docs declaration flips Wikipedia and OpenStreetMap to a screenshot with the warning above
— i.e. the check catches precisely the bug class it exists for.
pnpm testpasses.Related
*.wikipedia.organdwww.openstreetmap.orgfor the blockreference, so consuming sites inherit them instead of hand-maintaining the list.
🤖 Generated with Claude Code