From 7e6b2df1ade22bbfc7224eb77aa5603f24a85ef2 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Tue, 9 Jun 2026 19:07:15 +0200 Subject: [PATCH] fix(plugins): load plugin iframe via srcdoc to keep opaque-origin isolation on desktop Dropping allow-same-origin (so the plugin UI iframe runs on an opaque origin and cannot reach window.parent.ea) blanks the UI on packaged file:// builds: a blob: URL inherits the host origin and an opaque-origin iframe cannot fetch it. srcdoc is parsed inline (no cross-origin fetch), so the iframe renders under its opaque origin everywhere. - buildPluginIframeHtml() returns the document string (was createPluginIframeUrl returning a blob: URL); component binds it via [srcdoc] with bypassSecurityTrustHtml (srcdoc is a SecurityContext.HTML sink, raw strings would be sanitized). - remove now-unused blob URL tracking/cleanup. - sandbox stays a static attribute (Angular NG0910). (cherry picked from commit 5efab5d5ac2da5e6e1babf25e7e37d0d965b7559) --- src/app/plugins/plugin-cleanup.service.ts | 4 -- .../plugin-index/plugin-index.component.html | 9 ++-- .../ui/plugin-index/plugin-index.component.ts | 47 ++++++------------- .../plugins/util/plugin-iframe.util.spec.ts | 29 ++++++++++++ src/app/plugins/util/plugin-iframe.util.ts | 44 +++++------------ 5 files changed, 60 insertions(+), 73 deletions(-) diff --git a/src/app/plugins/plugin-cleanup.service.ts b/src/app/plugins/plugin-cleanup.service.ts index a7fcd01aad..d2133c1c02 100644 --- a/src/app/plugins/plugin-cleanup.service.ts +++ b/src/app/plugins/plugin-cleanup.service.ts @@ -1,5 +1,4 @@ import { Injectable } from '@angular/core'; -import { cleanupAllPluginIframeUrls } from './util/plugin-iframe.util'; /** * Simplified cleanup service following KISS principles. @@ -34,8 +33,5 @@ export class PluginCleanupService { cleanupAll(): void { // Just clear all references - let Angular manage iframe DOM lifecycle this._pluginIframes.clear(); - - // Clean up all blob URLs to prevent memory leaks - cleanupAllPluginIframeUrls(); } } diff --git a/src/app/plugins/ui/plugin-index/plugin-index.component.html b/src/app/plugins/ui/plugin-index/plugin-index.component.html index 190111d4df..5e59fa2ea9 100644 --- a/src/app/plugins/ui/plugin-index/plugin-index.component.html +++ b/src/app/plugins/ui/plugin-index/plugin-index.component.html @@ -59,16 +59,19 @@ } - @if (iframeSrc() && !error()) { + @if (iframeSrcdoc() && !error()) {
+ Angular forbids binding security-sensitive iframe attributes (throws NG0910). + No allow-same-origin: the iframe runs on an opaque origin so it cannot reach + window.parent.ea. Loaded via srcdoc (not a blob: URL) so it still renders on + packaged file:// builds, where an opaque-origin blob: fetch would be blocked. -->