Externe Websites sicher in der Vorschau anzeigen — Implementierung von Proxy + Sanitization + iframe Sandbox

HeatMapX Engineering Team5 min read
  • engineering
  • security
  • nextjs
  • iframe

Zusammenfassung dieses Artikels

  • Wenn eine externe Website in ein iframe der eigenen Origin geladen wird, besteht die Gefahr, dass externes JavaScript auf die eigene Sitzung zugreift
  • Die Lösung ist mehrschichtiger Schutz: „Proxy mit SSRF-Schutz + Entfernung von externem JS + restriktive CSP + iframe Sandbox"
  • Ist die Sandbox zu restriktiv, blockiert sie sogar das eigene Skript. Eine typische Falle ist das Vergessen von allow-scripts, wodurch die Funktion nicht mehr funktioniert

Die A/B-Tests von HeatMapX bieten eine Funktion, mit der man „das Aussehen der Änderung (Variante B), angewendet auf die Zielseite, in der Vorschau ansehen" kann. Technisch bedeutet das, „die externe Website eines Nutzers sicher innerhalb eines iframes der eigenen Domain anzuzeigen" – ein Vorgang, der überraschend heikel ist. In diesem Artikel teilen wir das Design und die Stolperfalle, in die wir dabei tatsächlich getappt sind.

Warum eine naive Implementierung gefährlich ist

Lädt man das HTML einer externen Website unverändert und liefert es über die eigene Origin aus (z. B. heatmapx.com), werden darin enthaltene <script>-Tags oder onclick=-Attribute mit den Rechten der eigenen Origin ausgeführt. Dadurch besteht die Gefahr, dass Cookies oder Login-Sitzungen ausgelesen werden. Das muss unbedingt verhindert werden.

Aufbau des mehrschichtigen Schutzes

Deshalb setzen wir folgende Schichten übereinander.

1. Proxy mit SSRF-Schutz

Die Ziel-URL wird validiert, alles außer http/https wird abgelehnt. Zusätzlich werden localhost, private IP-Adressen und Metadaten-Endpunkte von Cloud-Anbietern (z. B. 169.254.169.254) blockiert. Weiterleitungen werden nicht automatisch verfolgt, sondern über redirect: 'manual' Schritt für Schritt erneut geprüft, damit keine Umleitung ins interne Netzwerk erfolgen kann.

2. Entfernung von externem JS (Sanitization)

Aus dem geladenen HTML werden <script>-Tags, on*=-Inline-Handler und das javascript:-Schema entfernt. Das JavaScript der Kunden-Website muss in der Vorschau nicht ausgeführt werden (dass sich SPAs dadurch nicht vollständig originalgetreu darstellen lassen, ist ein bekannter und akzeptierter Kompromiss).

3. Restriktive CSP und base href

Direkt nach <head> wird ein <base href> eingefügt, um relative Pfade für Bilder und CSS aufzulösen. Gleichzeitig erhält die Antwort eine restriktive CSP, die verhindert, dass externes JavaScript ausgeführt wird. Bilder und CSS sind für die Darstellung erlaubt.

4. iframe Sandbox

Zum Schluss wird das anzeigende iframe zusätzlich mit sandbox isoliert.

Die Stolperfalle: Die Sandbox war zu restriktiv

Die Vorschau fügt in das geladene HTML ein kleines eigenes Skript ein, das die Änderung (changeSet) anwendet, und führt es im iframe aus, um das Erscheinungsbild anzupassen. Allerdings hatte das Vorschau-iframe im Sandbox-Attribut nur allow-same-origin gesetzt – allow-scripts fehlte.

Die Folge: Auch das eigene Skript wurde nicht ausgeführt, und die ursprüngliche Seite wurde angezeigt, ohne dass die Änderung angewendet wurde. Das iframe auf der Editor-Seite funktionierte hingegen korrekt mit allow-scripts allow-same-origin – die Ursache war also eine Inkonsistenz in der Konfiguration.

Die Korrektur war einfach: Auch die Vorschau-Seite auf allow-scripts allow-same-origin angleichen. Zusätzlich haben wir einen Regressionstest ergänzt, der das Sandbox-Attribut des iframes überprüft.

sandbox="allow-same-origin"  →  sandbox="allow-scripts allow-same-origin"

Erkenntnisse

  • Das Einbetten externer Inhalte sollte man immer als „mehrschichtigen Schutz" denken – nicht auf eine einzige Maßnahme verlassen.
  • Bei sandbox gilt nicht „einfach setzen und es ist sicher" – entscheidend ist, genau die benötigten Rechte präzise zu erlauben. Ist es zu restriktiv, blockiert es die eigene Funktion.
  • Bei „zwei Pfaden, die denselben Vorgang ausführen" (hier: Editor und Vorschau) muss man immer prüfen, ob die Sicherheitsattribute übereinstimmen. Korrigiert man nur einen der beiden, geht der andere kaputt.

Fazit

Eine sichere Vorschau externer Websites lässt sich durch mehrschichtigen Schutz erreichen: SSRF-Schutz, Entfernung von externem JS, restriktive CSP und iframe Sandbox. Dabei gilt: Die Rechte der Sandbox dürfen weder zu knapp noch zu großzügig sein. Das hier beschriebene Vergessen von allow-scripts war ein typisches Beispiel dafür.

Heatmaps aus Claude Code — kostenlos starten.

Ein Tracker-Tag einfügen, dann Analyse und CRO-Vorschläge aus der CLI bekommen.