Ihr SaaS will ein Plugin-Ökosystem. Web Components oder Iframes? Das CTO-Playbook

Von Diogo Hudson Dias
Front-end engineer in a São Paulo office reviewing a plugin running in a sandboxed iframe via Chrome DevTools, with security and network panels open.

Sie bekommen bei einem Plugin-Ökosystem keine zweite Chance. Sobald eine Extension zum ersten Mal die Daten des falschen Tenants liest oder Ihr localStorage kompromittiert, kaufen Sie sich ein verlorenes Quartal, eine PR-Schleife und ein Vertrauensdefizit ein, das Sie jahrelang abbezahlen. Ein jüngster Dev-Post, “Web Components vs. Iframes: A Hard Lesson in DOM Isolation Barriers”, ging herum, weil er eine stillschweigende Wahrheit offenlegte: Shadow DOM ist keine Sicherheitsgrenze. Wenn Sie 2026 einen Marktplatz oder eine „Extensions“-Fläche bauen, behandeln Sie UI-Komposition und Sicherheitsisolation als getrennte Entscheidungen — genau wie der Browser.

Das Problem, das Sie wirklich lösen

„Dritten erlauben, unsere App zu erweitern“ klingt nach einer Sache, ist aber vier verschiedene Probleme mit unvereinbaren Lösungen:

  • Ausführung nicht vertrauenswürdigen Codes: Kann ein Plugin beliebiges JS ausführen, ohne Daten zu exfiltrieren oder den Host zu kompromittieren?
  • DOM-Integration: Kann ein Plugin innerhalb Ihrer UI zeichnen, ohne dass Ihr Designsystem implodiert?
  • Daten- und Capability-Scoping: Kann ein Plugin nur das tun, wozu Nutzer und Tenant autorisieren — und nichts darüber hinaus?
  • Performance-Isolation: Können Sie verhindern, dass ein schlechtes Plugin INP, TTI oder den Speicher für alle ruiniert?

Wenn Sie das vermischen, wählen Sie das falsche Primitive. So landen Teams dabei, Web Components Sicherheitsarbeit machen zu lassen, die sie nicht leisten können, oder Iframes aufzublähen, obwohl die Seite sie nicht brauchte.

Die Kurzfassung

  • Wenn Sie jemals Drittentwicklern außerhalb Ihres Unternehmens erlauben, Code zu schreiben, nutzen Sie cross-origin Iframes für Ausführungsisolation. Punkt.
  • Verwenden Sie Web Components (Shadow DOM) für First-Party- oder geprüfte Partner-Bausteine, bei denen Sie tiefe DOM-Integration brauchen — nicht zum Sandboxing.
  • Verlagern Sie schwere oder langlaufende Plugin-Logik in Web Workers und kommunizieren Sie über Message-Channels. Workers sind keine Sicherheitsgrenze, halten aber den Main Thread gesund.
  • Ummanteln Sie alles mit Capability-gescopten Host-APIs. Geben Sie niemals rohe window-, document- oder storage-Handles an Plugin-Code weiter.

Das ist die Wirbelsäule. Die Details unten machen es produktionsreif.

Warum Web Components nicht Ihre Sandbox sind

Shadow DOM und Custom Elements lösen CSS- und Event-Leakage. Sie lösen keinen mandantenübergreifenden Datenschutz. Ein böswilliges oder schlicht fehlerhaftes Plugin in einem Web Component kann:

  • Jeden per JS zugänglichen Zustand lesen, den Sie übergeben (props, context, tokens).
  • fetch mit Ihren ambienten Anmeldedaten aufrufen, wenn Sie ihm Same-Origin-Zugriff auf Ihre APIs geben.
  • Über jeden offenen Host-Callback Daten exfiltrieren, den es erhält.

Ja, Sie können mit Trusted Types, strikter CSP und rigorosen Typgrenzen nachschärfen. Aber wenn der Entwickler außerhalb Ihrer Organisation ist — und Ihr Bedrohungsmodell „Plugin versucht mehr zu tun als erlaubt“ umfasst — sind Web Components für Komposition, nicht für Containment.

Warum cross-origin Iframes der langweilige, aber richtige Standard sind

Iframes sind günstige Sicherheit. Der Browser hat sie zwei Jahrzehnte lang gehärtet. Die Isolations-Primitiven, auf die Sie sich 2026 verlassen können:

  • Origin-Grenze: Andere Origin, andere ambiente Anmeldedaten. Third-Party-Cookies werden abgeschafft; hier ein Vorteil.
  • Sandbox-Attribut: Entfernen Sie allow-same-origin und das Iframe wird zu einer undurchsichtigen Origin. Gewähren Sie nur, was nötig ist: allow-scripts, allow-forms, vielleicht allow-popups-to-escape-sandbox für OAuth. Mikrofon, Kamera, USB, Payments standardmäßig deaktivieren.
  • Permissions Policy: Mächtige APIs pro Iframe verweigern. Keine Geolocation. Kein Window-Management. Kein Idle-Detector. Default-deny alles.
  • postMessage-basiertes RPC: MessageChannel isoliert Kommunikation auf explizite Ports. Bibliotheken wie Comlink machen es ergonomisch, ohne Referenzen zu leaken.

Abwägungen sind real. Jedes Iframe kostet Speicher (oft einige wenige MB), Layout-Komplexität und eine dünnere Integrationsschicht. Aber wenn ein Plugin von „irgendwem aus dem Internet“ kommt, ist das der Unterschied zwischen Incident-Report und Prahl-Post.

Ein pragmatischer Entscheidungsrahmen

1) Wer den Code schreibt und wen Sie verantwortlich machen, wenn es schiefgeht

  • Nur First-Party-Teams: Nutzen Sie Web Components für Ergonomie und Shadow DOM für Style-Isolation. Trotzdem den Zugriff über enge Host-APIs kapseln. Kein ambianter globaler Zustand.
  • Geprüfte strategische Partner unter Vertrag: Starten Sie mit Iframes für Isolation und exponieren Sie selektiv „DOM-ähnliche“ Flächen über Host-APIs. Wenn Sie unbedingt Web Components nutzen müssen, kapseln Sie Partnercode in einem Worker und vermitteln alle Host-Aufrufe über einen MessageChannel.
  • Offener Marktplatz: Cross-Origin-Iframes mit Sandbox und Permissions Policy. Keine Ausnahmen.

2) Was das Plugin tun muss

  • Schreibgeschützte UI-Widgets (Tabellen, Charts, Panels): Web Components sind für First-Party okay. Für Third-Party innerhalb eines Iframes rendern; Daten-Snapshots übergeben, keine Handles.
  • Mutierende Workflows (create/update/delete in Ihrer App): Immer per Capability-Scoping über signierte Action-Tokens serverseitig pro Tenant–Ressource–Operation mit 5–15 Minuten TTL. Keine Bearer-Token mit globaler Autorität.
  • Schwere Rechenarbeit (Parsing, KI-Transforms): In einen Worker innerhalb der Iframe-Origin oder in Ihre serverseitige Extension-Runtime auslagern. Long Tasks auf dem Main Thread verhindern: Budget maximal 50 ms pro Interaktion; drosseln oder per scheduler.postTask({priority: "background"}) yielden.
  • Netzwerkzugriff: Bevorzugen Sie eine Host-proxied fetch-API, die CORS durchsetzt, Requests loggt, Cookies entfernt und Rate Limits anwendet. Keinen rohen Netzwerkzugriff für untrusted Plugins gewähren.

3) Wie tief die visuelle Integration sein muss

  • „Fühlt sich wie Teil der App an“: Für Iframes eine Design-Token-Bridge shippen: CSS-Variablen und eine Light/Dark-Palette via Handshake-Nachricht beim Iframe-Load exponieren. Teilen Sie nicht Ihre gesamte Designsystem-Runtime; senden Sie aufgelöste Tokens.
  • Events, Fokus, ARIA: Für Barrierefreiheit Top-Level-Host-Events (resize, theme-change, locale-change) über einen dedizierten MessagePort proxi-en. Im Iframe liegen die ARIA-Semantiken beim Plugin. Sie können A11y über Frames nicht so eng garantieren wie in Shadow-Trees; setzen Sie diese Erwartung.
  • Drag/Drop, Auswahl, Overlay-Portale: Das sind Schmerzpunkte. Stellen Sie Host-verwaltete Primitiven bereit: host-eigenes Overlay-Portal-API; host-eigene Drag/Drop-Koordination, die Intents an Plugins sendet, statt ihnen globale Listener zu geben.

Sicherheitskontrollen, die Sie ab Tag eins einbauen sollten

  • CSP auf Host- und Plugin-Origins: Host: script-src 'self' + Hashes für Ihre Skripte, kein 'unsafe-inline'. Plugin-Origin: separate CSP ohne Remote Code Execution über das Bundle hinaus. Für Web-Component-Ladevorgänge mit SRI und exakten Versionen pinnen.
  • Permissions-Policy-Baseline: Standardmäßig alles verweigern: geolocation=(), camera=(), microphone=(), payment=(), usb=(), battery=(), clipboard-write=() außer bei klarem Produktbedarf.
  • Iframe-Sandbox-Vertrag: sandbox="allow-scripts allow-forms" mindestens; vermeiden Sie allow-same-origin. allow-popups und allow-popups-to-escape-sandbox nur für OAuth-Flows hinzufügen; Message-Channels nach Abschluss der Auth terminieren.
  • Capability-Tokens, nicht Session-Cookies: Schlanke JWTs ausstellen: {tenant, resource, operation, plugin_id, exp ≤ 15m}. An das Iframe via Message-Port-Initialisierung binden; globale Session-Tokens niemals an Plugin-JS exponieren.
  • Rate Limiting und Egress-Logging pro plugin_id: Jeder host-vermittelte Call wird gemessen und mit Tenant- und Plugin-Kennungen getaggt. Sie brauchen das, wenn das Finance-Team fragt, warum ein Plugin den Egress um 3 TB explodieren ließ.
  • Trusted Types + DOMPurify (strict): Für jedes HTML-Rendering, das der Host im Auftrag eines Plugins vornimmt, TrustedHTML verlangen. Cross-Frame-HTML bis zur Desinfektion als feindlich behandeln.

Performance- und UX-Budgets, die Sie durchsetzen können

  • Speicher: Rechnen Sie mit 3–8 MB Baseline pro Iframe in modernem Chromium. Auf einem Dashboard mit 6 Plugins sind das ~30–50 MB. Machen Sie eine harte Obergrenze: maximal 4 gleichzeitig sichtbare Third-Party-Iframes; den Rest lazy-loaden.
  • Interaktionslatenz (INP): Budget ≤ 200 ms p95. Jedes Plugin, das mehr als 5 Mal pro Minute Long Tasks > 50 ms erzeugt, wird über Ihren Host-Scheduler gedrosselt und im Marktplatz markiert.
  • Netzwerk: Plugin-Requests pro Tenant standardmäßig auf 10 RPS deckeln, Burst ≤ 50. Alles, was KI-bezogen ist, wandert in Ihre serverseitige Extension-Runtime, um Tokenkosten und Latenz planbar zu halten.
  • Cold Start: Iframes booten langsamer. Versteckte Iframes mit loading="lazy" vorinitialisieren und während Idle-Zeitfenstern einen expliziten Warmup-Handshake durchführen. Rechnen Sie mit 80–200 ms zusätzlicher TTI gegenüber In-Page-Code — abhängig von der Bundlegröße.

Die Developer Experience, die Sie Ihrem Ökosystem schulden

Sicherheit ohne DX stirbt beim ersten Kontakt mit der Realität. Geben Sie Plugin-Entwicklern einen Vertrag, der leicht zu befolgen und schwer zu missbrauchen ist:

  • Manifest + Capabilities: Ein JSON-Manifest, das Routen, UI-Mountpoints und angeforderte Capabilities deklariert. Bei der Registrierung ablehnen, wenn es mehr verlangt, als für seine Kategorie erlaubt ist.
  • Getypte Host-API: Ein TypeScript-SDK, das postMessage mit Comlink kapselt, Capability-Scopes zur Compile-Zeit durchsetzt und Mocks für die lokale Entwicklung bereitstellt.
  • Design Tokens, nicht Ihr CSS: Tokens für Farbe, Abstände und Typografie über ein stabiles JSON-Schema exportieren; Plugins mappen ihre eigenen Komponenten. Koppeln Sie Ihre Release-Kadenz nicht an das CSS Dritter.
  • Lokaler Dev-Container: Ein CLI, das einen localhost-Iframe-Host mit derselben Sandbox und denselben Policys wie in Prod startet. Kein „läuft nur lokal“–Drift.
  • Observability: Eine Plugin-Konsole bereitstellen: Logs, Netzwerkanrufe, Rate-Limit-Treffer, Capability-Verweigerungen. p95-Initzeit und INP für Entwickler sichtbar machen, damit sie tunen können.

Marktplatz-Policy, die Haftung wirklich verlagert

Wenn Sie externen Code gegen die Daten Ihrer Kunden laufen lassen, agieren Sie wie eine Plattform:

  • Security-Review-Tiers: Bronze (nur automatisierte Checks), Silber (manuelle Prüfung + Code-Scan + Penetrationstest), Gold (jährliche Re-Zertifizierung, SOC 2 Report). Bepreisen Sie Ihren Revenue Share entsprechend.
  • Key-Escrow für Takedowns: Jeder Plugin-Release muss adressierbar sein: signiertes Bundle mit reproduzierbaren Build-Metadaten. Wenn Sie widerrufen müssen, können Sie es. Nutzen Sie Subresource Integrity für Script-Delivery, wo möglich.
  • Incident-Playbook: One-Click-Disable pro Tenant und globaler Kill Switch. Verlangen Sie, dass Plugins eine „Safe Mode“-Route für Datenexport und Uninstall implementieren.
  • Transparenter Daten-Footprint: Öffentlich dokumentieren, was ein Plugin darf und welche Capabilities es nutzt. So veröffentlichen, dass Käufer nach Risikoprofil filtern können.

Serverseitige Extensions: Zwingen Sie nicht alles in den Browser

Vieles von „wir brauchen tiefen DOM-Zugriff“ ist selbstverschuldet. Trennen Sie die Welt:

  • Client-seitige visuelle Flächen: Nutzen Sie Iframes oder Web Components gemäß den obigen Regeln.
  • Server-seitige Aktionen und Automatisierungen: Laufen in Ihrer Extension-Runtime (Node, Deno oder WASM) mit strikter Mandantentrennung, geprüftem Egress und signierten Requests zurück an Ihre Kern-APIs. Das Browser-UI stößt nur Intents an.

So senken Sie den Druck, dem Browser-Plugin übermäßige Berechtigungen zu geben, nur um an Daten oder GPUs zu kommen, die es nie berühren sollte.

Was 2026 neu ist — und warum es Sie kümmern sollte

  • Abschaffung von Third-Party-Cookies: Spielt Ihnen in die Karten. Cross-Origin-Iframes erben Ihre Session nicht. Von Tag eins für tokenbasierte Capabilities designen.
  • Fenced Frames: Super für ad-ähnliche, untrusted Inhalte mit Privacy-Garantien, aber noch zu eingeschränkt für die meisten App-Plugins. Support beobachten; die Plattform noch nicht darauf aufbauen.
  • Base UI, shadcn/ui-Churn: Jüngste Component-Library-Migrationen erinnern: Designsysteme ändern sich; Sicherheitsgrenzen nicht. Halten Sie Sicherheit orthogonal zu Ihrem UI-Stack.

Eine Referenzarchitektur, die Sie kopieren können

  1. Registry-Service: Speichert Plugin-Manifeste, signierte Bundle-Metadaten und Capabilities. Erzwingt Kategorierichtlinien beim Publish.
  2. Host-Shell (App): Rendert Plugin-Mountpoints. Injiziert für untrusted Plugins Cross-Origin-Iframes mit sandbox- und allow-Attributen pro Capability. Initialisiert einen MessageChannel pro Plugin.
  3. Host-SDK: Typ-sicherer Wrapper um postMessage/Comlink. Exponiert APIs: data.read(resource), actions.execute(actionToken), ui.openOverlay(), storage.session.get/set (scoped to plugin_id+tenant).
  4. Policy-Gateway: Serverseitiger Dienst, der kurzlebige Capability-Tokens ausstellt und Plugin-Netzwerk-Egress mit Logging und Rate Limits proxi-t. Bindet Tokens an tenant+plugin_id+operation.
  5. Serverseitige Extension-Runtime: Führt schwere oder sensible Schritte unter Ihrer Kontrolle aus. Kommuniziert mit Core-Services via mTLS und signierten Requests. Exponiert Webhooks, über die das Plugin-Iframe Updates erhält.
  6. Observability-Ebene: Dashboards pro Plugin: Initzeit, INP, Fehlerrate, Egress, Capability-Verweigerungen. Automatische Marktplatz-Flags für Ausreißer.
  7. Kill Switch und Feature Flags: Zentrale Toggles, um eine Version oder Capability sofort mandantenübergreifend zu widerrufen.

Häufige Fallen (und die Lösung)

  • Falle: Ihren Redux-Store oder React-Context mit einem Web-Component-Plugin teilen. Lösung: Nur Read-only-Snapshots via Structured Clone exponieren; alle Writes laufen über Capability-gated Host-Aktionen.
  • Falle: allow-same-origin dem Iframe hinzufügen, weil ein Dev Cookies brauchte. Lösung: Nicht tun. Auth über den Host proxi-en; wenn es unbedingt sein muss, diesen Flow in ein dediziertes Auth-Iframe isolieren, mit quarantiniertem Kanal, und danach zerstören.
  • Falle: Plugins globale Event-Listener registrieren lassen. Lösung: Gescopte, host-eigene Event-APIs bereitstellen und drosseln.
  • Falle: Version-Drift Ihres Designsystems bricht Plugins. Lösung: Design-Tokens versionieren und mindestens zwei parallele Major-Versionen unterstützen. Der Plugin-Vertrag sind Tokens, nicht Klassennamen.

Warum das für KI-lastige Apps zählt

Agenten-Integrationen vergrößern das Risiko. Ein Plugin, das alles sehen kann, wird früher oder später per Prompt-Injection dazu gebracht, alles zu tun. Halten Sie Modellkontexte schmal: Wenn ein Plugin um KI-Hilfe bittet, assembliert der Host Kontextschnipsel, redigiert Secrets und signiert den Request für das Modell. Kein Plugin sollte jemals rohe API-Schlüssel oder tenant-globale Embeddings halten. Rechnen Sie mit regulatorischer Aufmerksamkeit — bald.

Was wir für Kunden bei DHD Tech tun

Wir haben Plugin-Plattformen für US-SaaS-Teams ausgeliefert, bei denen die Differenz zwischen „schöner App“ und „verteidigungsfähiger Plattform“ Wochen statt Quartale beträgt. Unser Default-Stack ist:

  • Cross-Origin-Iframes für Third-Party-Code mit Sandbox und strikter Permissions Policy.
  • Getypte Host-APIs über Comlink, mit mandanten- und fähigkeitsbasierten JWTs, die in 5–15 Minuten ablaufen.
  • Design-Token-Bridges für visuelle Kohärenz ohne CSS-Verflechtung.
  • Serverseitige Extension-Runtimes für schwere/regulierte Workloads, mit budgetiertem Egress und Token-Accounting.
  • Automatisierte Konformitätstests, die in CI 50+ synthetische Plugins hochfahren, um Isolation, Rate Limits und Performance-Budgets unter Last zu validieren.

Das ist mit Absicht langweilig. Die Alternative ist, zu einem Vorfall-Thread aufzuwachen, der behauptet, jemandes „private Videos“ seien wegen Ihres Cross-Tenant-Bugs geleakt. Seien Sie nicht dieser Post.

Wichtigste Erkenntnisse

  • Cross-Origin-Iframes für jeden Code, den Sie nicht kontrollieren; Web Components sind für Komposition, nicht für Containment.
  • Enge, Capability-gescopte Host-APIs exponieren; niemals rohes DOM, Storage oder globale Tokens an Plugins weitergeben.
  • Budgets durchsetzen: Speicher pro Iframe, p95 INP, Netzwerk-RPS und Kill Switches für Bad Actors.
  • Design Tokens überbrücken die visuelle Integration; teilen Sie nicht Ihre Designsystem-Runtime.
  • Client-UI von serverseitigen Extensions trennen; Sensitives und Schweres gehört nicht in den Browser.
  • In Manifest, TypeScript-SDK, lokalen Host und Observability investieren, damit der sichere Pfad der einfache ist.

Ready to scale your engineering team?

Tell us about your project and we'll get back to you within 24 hours.

Start a conversation