From 2158eab001edc2431393a553ebbcfe32096d1877 Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Tue, 21 Apr 2026 16:25:03 +0100 Subject: [PATCH] fix(basic-host): accept Safari same-origin event.source in sandbox relay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Safari/WebKit can surface inner-iframe messages at the sandbox relay with event.source === window (the sandbox's own window) rather than inner.contentWindow. The strict source-identity check then drops the View's ui/initialize and the handshake never completes. Accept that case when event.origin === OWN_ORIGIN — the sandbox runs on its own dedicated origin, so origin is the real security boundary here. Source-identity remains the primary check on Chromium where it works. --- examples/basic-host/src/sandbox.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/basic-host/src/sandbox.ts b/examples/basic-host/src/sandbox.ts index 6f1dd93d7..c7900b57e 100644 --- a/examples/basic-host/src/sandbox.ts +++ b/examples/basic-host/src/sandbox.ts @@ -112,7 +112,14 @@ window.addEventListener("message", async (event) => { inner.contentWindow.postMessage(event.data, "*"); } } - } else if (event.source === inner.contentWindow) { + } else if ( + event.source === inner.contentWindow || + // Safari/WebKit can surface inner-iframe messages with `event.source === + // window` (the sandbox's own window) instead of `inner.contentWindow` in + // nested same-origin setups. Origin is the real security boundary here — + // the sandbox runs on its own dedicated origin — so accept that case too. + (event.origin === OWN_ORIGIN && event.source === window) + ) { if (event.origin !== OWN_ORIGIN) { console.error( "[Sandbox] Rejecting message from inner iframe with unexpected origin:",