Layer 8Ehrlicher Tech-Support
SoftwareSchweregrad: LästigRefused to display 'https://example.com/' in a frame because it set 'X-Frame-Options' to 'deny'.

Fremde Seite lässt sich nicht einbetten: X-Frame-Options verbietet es

Der eingebettete Rahmen bleibt weiß, die Konsole meldet verweigertes Anzeigen. Die fremde Seite untersagt das Einbetten per Kopfzeile — mit Absicht.

Aufwand:
ca. 20 Min.
Voraussetzung:
Ein Browser mit Entwicklerwerkzeugen, Terminal mit curl, Zugriff auf die Serverkonfiguration der einzubettenden Seite
Gilt für:
RFC 7034 (Informational, Oktober 2013), W3C Content Security Policy Level 3, Working Draft vom 29.07.2026

Das Symptom

Auf der eigenen Seite soll ein fremder Inhalt erscheinen — der Fahrplan des Verkehrsverbunds, das Buchungsformular des Anbieters, das Kundenportal einer Bank. Der Rahmen ist eingebaut, die Adresse stimmt, im eigenen Tab lädt die Seite tadellos. Im Rahmen bleibt sie weiß. Manchmal blitzt kurz etwas auf und verschwindet wieder. In der Konsole steht eine Zeile, die mit „Refused to display“ beginnt.

Die „Layer 8“-Wahrheit

Hier ist nichts kaputt. Hier funktioniert eine Absperrung, und zwar exakt so, wie sie gedacht ist. Der Denkfehler steckt in der Annahme, das Einbetten sei die Entscheidung dessen, der einbettet. Sie ist es nicht. Sie gehört dem, dessen Inhalt eingebettet werden soll, und durchgesetzt wird sie vom Browser des Besuchers — also an zwei Stellen, an denen du nichts zu bestimmen hast.

Der Grund für diese Absperrung heißt Clickjacking und ist unangenehm einfach: Ein Angreifer lädt die echte Seite eines Anbieters in einen unsichtbaren Rahmen, legt seine eigene harmlose Oberfläche darüber und positioniert sie so, dass ein Klick auf „Weiter“ in Wahrheit den Schalter im fremden Rahmen trifft. Der Besucher ist dort angemeldet, also führt die fremde Seite die Aktion bereitwillig aus. Sie sieht ja einen ganz normalen Klick eines angemeldeten Nutzers. Genau dagegen wurde 2013 die Kopfzeile X-Frame-Options standardisiert; die CSP-Spezifikation nennt dieselbe Gefahr heute unter dem Oberbegriff UI Redressing.

Zwei Mechanismen existieren nebeneinander, was regelmäßig für Verwirrung sorgt. Der ältere ist grob: DENY verbietet jedes Einbetten, SAMEORIGIN erlaubt es nur der eigenen Herkunft — Zwischenstufen gibt es nicht. Der Wert ALLOW-FROM war einmal als Freigabe für einzelne Partner gedacht, wurde aber nie überall umgesetzt und ist praktisch tot. Der neuere Mechanismus ist die CSP-Regel frame-ancestors, die eine echte Liste erlaubter Domains kennt, und wo beide gesendet werden, gewinnt sie: Die Spezifikation legt fest, dass sie die alte Kopfzeile übersteuert.

Für alle, die etwas einbetten wollen, folgt daraus eine kurze Anweisung. Sieh mit curl nach, was der fremde Server sendet, statt im Rahmen weiter herumzuraten. Steht dort ein Verbot, ist das Thema für dich beendet — frag den Betreiber, oder setz einen Link. Und für den umgekehrten Fall, in dem die Seite dir gehört: Die Regel gehört in eine echte HTTP-Kopfzeile. Im meta-Element des Dokuments wird sie laut Spezifikation ignoriert, und zwar aus einem sehr handfesten Grund — bis der Browser dort ankommt, hat er die Seite längst in den fremden Rahmen geladen.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Die Meldung in der Konsole lesen

    Mit F12 die Entwicklerwerkzeuge öffnen und in die Konsole schauen. Dort steht, welcher der beiden Mechanismen zugeschlagen hat: eine Meldung mit `X-Frame-Options` oder eine, die eine Richtlinie mit `frame-ancestors` nennt. Beide sagen dasselbe aus — der eingebettete Server hat das Anzeigen verweigert —, aber die Reparatur setzt an unterschiedlichen Stellen an.

  2. 2.

    Nachsehen, was der fremde Server tatsächlich sendet

    Die Konsole zeigt die Wirkung, dieser Befehl die Ursache. Er holt nur die Kopfzeilen der Antwort und filtert die beiden Zeilen heraus, um die es geht. Kommt keine Ausgabe, liegt es nicht am Einbettungsschutz und du suchst an der falschen Stelle weiter.

    curl -sSI https://example.com/ | grep -i -E "^x-frame-options:|^content-security-policy:"
    
  3. 3.

    Den gefundenen Wert richtig deuten

    `DENY` heißt: in keinem Rahmen, von niemandem, niemals. `SAMEORIGIN` heißt: nur auf der eigenen Herkunft — für dich als Fremde also ebenfalls nein. Bei `frame-ancestors` steht dahinter eine Liste erlaubter Quellen; `'none'` entspricht ungefähr `DENY`, `'self'` ungefähr `SAMEORIGIN`. Steht deine Domain nicht in der Liste, ist die Antwort nein. Ein wichtiger Hinweis aus RFC 7034 zu `SAMEORIGIN`: Kann ein Browser nicht zuverlässig feststellen, ob Inhalt und Rahmen dieselbe Herkunft haben, muss er das wie `DENY` behandeln.

  4. 4.

    Wenn dir die Seite gehört: die Regel gezielt setzen

    Die moderne und feiner steuerbare Variante ist die CSP-Regel. Sie erlaubt eine Liste konkreter Partner statt der Alles-oder-nichts-Entscheidung der alten Kopfzeile. Wichtig: als echte HTTP-Kopfzeile ausliefern, nicht im `meta`-Element, und daran denken, dass diese Regel nicht auf `default-src` zurückfällt. Beispiel für nginx:

    add_header Content-Security-Policy "frame-ancestors 'self' https://partner.example" always;
    
  5. 5.

    Die alte Kopfzeile als Auffangnetz danebenstellen

    Sehr alte Browser kennen `frame-ancestors` nicht. Weil die CSP-Regel die alte Kopfzeile ohnehin übersteuert, wo beide verstanden werden, kostet das Mitsenden nichts und deckt den Rest ab. `SAMEORIGIN` erlaubt dabei die eigene Herkunft; eine Freigabe für einzelne Partner kann diese Kopfzeile nicht — dafür ist die CSP-Regel zuständig. Für Apache:

    Header always set X-Frame-Options "SAMEORIGIN"
    
  6. 6.

    Die Änderung überprüfen, statt sie zu glauben

    Nach dem Neuladen der Serverkonfiguration noch einmal die Kopfzeilen abrufen und danach die einbettende Seite mit geleertem Zwischenspeicher testen. Ein häufiger Stolperstein: Ein vorgelagerter Zwischenspeicher oder ein Auslieferungsnetz liefert die alte Antwort weiter, und du misst die Vergangenheit.

    curl -sSI https://example.com/ | grep -i -E "^x-frame-options:|^content-security-policy:"
    
  7. 7.

    Wenn die Seite dir nicht gehört: den Betreiber fragen oder umbauen

    Bleibt es beim Nein, gibt es zwei ehrliche Wege. Erstens: den Betreiber bitten, deine Domain in seine Liste erlaubter Vorfahren aufzunehmen — bei Geschäftspartnern ist das ein normaler Vorgang. Zweitens: statt des Rahmens einen normalen Link setzen, der die Seite in einem neuen Tab öffnet. Das ist nicht die elegante Lösung, aber die einzige, die dauerhaft funktioniert.

Häufige Fragen (FAQ)

?Kann ich das irgendwie umgehen?

Nicht von deiner Seite aus, und das ist der springende Punkt. Die Entscheidung trifft der Server, dem der Inhalt gehört, und durchgesetzt wird sie vom Browser des Besuchers. Du hast an keiner der beiden Stellen etwas zu melden. RFC 7034 formuliert das für den Wert `DENY` als Pflicht des Browsers: „A browser receiving content with this header field MUST NOT display this content in any frame.“ Es gibt kein Attribut am Rahmen, keine Einstellung und keinen Trick, der das aushebelt — außer den Betreiber zu fragen, ob er deine Domain freigibt. Alles, was im Netz als Umgehung kursiert, läuft darauf hinaus, die fremde Seite über einen eigenen Server zu spiegeln, und das ist urheberrechtlich wie sicherheitstechnisch eine eigene Baustelle.

?Warum sperren Seiten das überhaupt? Ich will doch nur verlinken.

Wegen Clickjacking. Ein Angreifer bettet die echte, korrekt angemeldete Seite eines Anbieters unsichtbar in seine eigene ein, legt eine harmlos aussehende Oberfläche darüber und bringt den Besucher dazu, auf einen Schalter zu klicken, der in Wirklichkeit im fremden Rahmen liegt — Überweisung bestätigen, Berechtigung erteilen, Konto löschen. RFC 7034 nennt genau das als Zweck der Kopfzeile: die Verbesserung des Schutzes von Webanwendungen gegen Clickjacking. Die CSP-Spezifikation beschreibt dieselbe Absicht für `frame-ancestors`, nämlich das Risiko zu vermeiden, in möglicherweise feindliche Zusammenhänge eingebettet zu werden. Banken, Verwaltungsportale und Anmeldeseiten sperren deshalb praktisch immer.

?Ich habe beides gesetzt, `X-Frame-Options` und `frame-ancestors` — welches gilt?

`frame-ancestors` gewinnt. Die CSP-Spezifikation regelt das ausdrücklich: „In order to allow backwards-compatible deployment, the frame-ancestors directive overrides the X-Frame-Options header.“ Wird eine durchzusetzende Richtlinie mit dieser Regel ausgeliefert, ignoriert der Browser die alte Kopfzeile vollständig. Beides zu senden ist trotzdem sinnvoll — die alte Kopfzeile ist das Auffangnetz. Wichtig ist nur, dass beide dasselbe aussagen, sonst debuggst du später eine Regel, die gar nicht angewendet wird.

?Warum wirkt meine CSP-Regel nicht, obwohl sie in der Seite steht?

Vermutlich steht sie im `meta`-Element im Kopf des Dokuments statt in einer echten HTTP-Kopfzeile. Für diese Regel ist das wirkungslos, und die Spezifikation sagt es unmissverständlich: „The frame-ancestors directive MUST be ignored when contained in a policy declared via a meta element.“ Das ist auch logisch — bis der Browser das `meta`-Element im HTML gelesen hat, hat er die Seite bereits in den Rahmen geladen. Die Entscheidung muss fallen, bevor irgendetwas dargestellt wird, also gehört sie in die Antwort des Servers. Ein zweiter häufiger Grund: `frame-ancestors` fällt nicht auf `default-src` zurück. Eine Richtlinie mit `default-src 'none'` erlaubt das Einbetten weiterhin für jeden.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler

SWLästigMixed Content: The page at … was loaded over HTTPS, but requested an insecure … This request has been blocked; the content must be served over HTTPS.

Sichere Seite bleibt halb leer: Gemischte Inhalte werden blockiert

Die Seite läuft über HTTPS, lädt aber Bilder oder Skripte per HTTP nach. Der Browser blockiert sie — und die halbe Seite fehlt. Warum das gut ist.

SWLästigblocked by CORS policy

Browser blockiert Anfrage wegen CORS

Die Konsole meldet einen CORS-Fehler und die Anfrage scheitert? Nicht der Browser ist schuld — der Server muss den Zugriff von deiner Herkunft erlauben.

SWLästigNET::ERR_CERT_AUTHORITY_INVALID

Browser: NET::ERR_CERT_AUTHORITY_INVALID

Der Browser warnt, das Zertifikat stamme von keiner vertrauenswürdigen Stelle? Oft schneidet Software mit oder es ist selbst signiert.