Skip to content

fix(preview): don't crash the preview panel on a malformed iframe URL - #6362

Merged
pedrofrxncx merged 1 commit into
mainfrom
fix/preview-url-helpers-malformed-url-w4
Aug 20, 2026
Merged

fix(preview): don't crash the preview panel on a malformed iframe URL#6362
pedrofrxncx merged 1 commit into
mainfrom
fix/preview-url-helpers-malformed-url-w4

Conversation

@pedrofrxncx

@pedrofrxncx pedrofrxncx commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Follows #6357 (withDecoFBT) hardening.

withDeviceHint and withDecoFBT in preview.tsx call new URL(url, window.location.href) directly in the render path with no guard. Right next to them, previewOrigin already treats a malformed URL as non-fatal (try { ... } catch { return null }) — these two don't follow that pattern.

Failure scenario: if directPreviewUrl/previewUrl (sourced from the sandbox daemon / draft preview state) is ever an unparseable string — e.g. http://[::1 (bad IPv6 literal) — new URL(...) throws synchronously during render, taking down the whole PreviewContent tree instead of just failing to apply the deviceHint/__decoFBT query param.

Fix: wrap both in try/catch and fall back to returning the original url unmodified, matching previewOrigin's existing shape in the same file.

Regression test: apps/web/src/components/sandbox/preview/preview.test.ts — exercises both helpers on a well-formed URL and on a URL that throws inside the WHATWG URL parser (http://[::1), asserting the malformed case returns the input unchanged instead of throwing.

Reviewer check: bun test apps/web/src/components/sandbox/preview/preview.test.ts

Locally verified: bun run fmt (no changes), cd apps/web && bunx tsc --noEmit (clean), bunx oxlint on both changed files (0 warnings/errors), targeted test above (5/5 pass). Full CI covers the rest.


Summary by cubic

Prevents the preview panel from crashing on a malformed iframe URL by hardening withDeviceHint and withDecoFBT. Previously new URL(...) threw during render; now both helpers catch parse errors and return the original URL, so only the query param is skipped.

  • Behavior: malformed previewUrl/directPreviewUrl no longer breaks PreviewContent; deviceHint/__decoFBT may be omitted in that case. Matches previewOrigin’s defensive handling.
  • Review: see apps/web/src/components/sandbox/preview/preview.tsx (try/catch wrappers). Tests in apps/web/src/components/sandbox/preview/preview.test.ts; run bun test apps/web/src/components/sandbox/preview/preview.test.ts.

Written for commit 84895b0. Summary will update on new commits.

Review in cubic

withDeviceHint and withDecoFBT (added in #6357) call `new URL(url, ...)`
directly in the render path with no guard, unlike the adjacent previewOrigin
helper which already treats a malformed URL as non-fatal. A bad
directPreviewUrl/previewUrl (e.g. an unparseable IPv6 host from the sandbox
daemon) throws mid-render and takes down the whole preview panel instead of
just failing to apply the deviceHint/__decoFBT param.

Wrap both in try/catch and fall back to the original url, matching
previewOrigin's existing shape.
@pedrofrxncx
pedrofrxncx merged commit eefc905 into main Aug 20, 2026
34 checks passed
@pedrofrxncx
pedrofrxncx deleted the fix/preview-url-helpers-malformed-url-w4 branch August 20, 2026 19:35
pedrofrxncx added a commit that referenced this pull request Aug 20, 2026
… URL (#6374)

#6362 wrapped withDeviceHint/withDecoFBT's new URL() calls in try/catch
after a malformed directPreviewUrl/previewUrl crashed the whole preview
panel mid-render, matching previewOrigin's existing defensive shape.

It missed four sibling call sites that construct URLs from the same
untrusted display.iframeBase (sandbox daemon / production preview server
config): productionOrigin, the two iframeSrc branches, and
productionOpenTabBase. Each still calls new URL(...) unguarded as an
argument expression, so a malformed iframeBase (e.g. an unparseable host)
throws before withDeviceHint/withVariantMatcherOverride's own try/catch
ever runs, taking the panel down the same way #6362 fixed for the other
inputs.

Added resolvePreviewUrl(), the same try/catch-and-fall-back-to-null shape
as previewOrigin, and use it (or previewOrigin itself) at all four sites.
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