fix(studio): guard cross-origin iframe access to prevent SecurityError crashes

Wrap all contentWindow/contentDocument access and addEventListener/removeEventListener
calls in try/catch across usePlaybackKeyboard, useAppHotkeys, and CompositionsTab.
Prevents SecurityError from propagating to the React error boundary (white screen).
Affects 1,885 crashes / 648 unique users in the last 7 days.
This commit is contained in:
Miguel Ángel
2026-05-25 16:49:40 +00:00
parent 179241e932
commit c1b26fcb32
3 changed files with 122 additions and 53 deletions
@@ -182,23 +182,38 @@ export function usePlaybackKeyboard({
playbackKeyDownRef.current = handlePlaybackKeyDown;
playbackKeyUpRef.current = handlePlaybackKeyUp;
// fallow-ignore-next-line complexity
const attachIframeShortcutListeners = useCallback(() => {
iframeShortcutCleanupRef.current?.();
iframeShortcutCleanupRef.current = null;
const iframeWin = iframeRef.current?.contentWindow;
const iframeDoc = iframeRef.current?.contentDocument;
let iframeWin: Window | null = null;
let iframeDoc: Document | null = null;
try {
iframeWin = iframeRef.current?.contentWindow ?? null;
iframeDoc = iframeRef.current?.contentDocument ?? null;
} catch {
return;
}
if (!iframeWin && !iframeDoc) return;
const handleIframeKeyDown = (e: KeyboardEvent) => playbackKeyDownRef.current(e);
const handleIframeKeyUp = (e: KeyboardEvent) => playbackKeyUpRef.current(e);
iframeWin?.addEventListener("keydown", handleIframeKeyDown, true);
iframeWin?.addEventListener("keyup", handleIframeKeyUp, true);
try {
iframeWin?.addEventListener("keydown", handleIframeKeyDown, true);
iframeWin?.addEventListener("keyup", handleIframeKeyUp, true);
} catch {
/* cross-origin iframe */
}
iframeDoc?.addEventListener("keydown", handleIframeKeyDown, true);
iframeDoc?.addEventListener("keyup", handleIframeKeyUp, true);
iframeShortcutCleanupRef.current = () => {
iframeWin?.removeEventListener("keydown", handleIframeKeyDown, true);
iframeWin?.removeEventListener("keyup", handleIframeKeyUp, true);
try {
iframeWin?.removeEventListener("keydown", handleIframeKeyDown, true);
iframeWin?.removeEventListener("keyup", handleIframeKeyUp, true);
} catch {
/* cross-origin iframe */
}
iframeDoc?.removeEventListener("keydown", handleIframeKeyDown, true);
iframeDoc?.removeEventListener("keyup", handleIframeKeyUp, true);
};