Nach den Spectre- und Meltdown-Angriffen (2018) hat das Web-Plattform-Team begonnen, Cross-Origin-Isolation strukturell zu verbessern. Das Ergebnis: COOP, COEP und CORP — drei Header, die zusammen eine Web-Seite als „cross-origin isolated" markieren. In diesem Zustand kann der Browser die Seite in einen eigenen Prozess setzen (gegen Spectre-Side-Channels), bestimmte Features wie SharedArrayBuffer werden freigeschaltet, und Cross-Window-Manipulation wird verhindert.

Die drei Header im Überblick

HeaderWofürWerte
Cross-Origin-Opener-Policy (COOP)Isoliert die Seite von Cross-Origin-Window-Referenzensame-origin, same-origin-allow-popups, unsafe-none
Cross-Origin-Embedder-Policy (COEP)Verlangt, dass eingebettete Ressourcen explizit zustimmenrequire-corp, credentialless, unsafe-none
Cross-Origin-Resource-Policy (CORP)Sagt, wer diese Ressource einbetten darfsame-origin, same-site, cross-origin

COOP und COEP werden auf die HTML-Seite gesetzt, CORP auf die eingebetteten Ressourcen (Bilder, Skripte, Iframes).

Wenn COOP=same-origin UND COEP=require-corp gesetzt sind, ist die Seite cross-origin isolated. Folgen:

  • Eigener Browser-Prozess möglich (Spectre-Schutz).
  • SharedArrayBuffer und performance.now() mit hoher Auflösung freigeschaltet.
  • window.opener zu cross-origin-Fenstern ist null.

COOP — Cross-Origin-Opener-Policy

Problem: Wenn deine Seite ein Popup öffnet oder von einem fremden Tab via window.open() geöffnet wurde, haben beide Seiten via window.opener Zugriff aufeinander. Das hat in der Vergangenheit zu mehreren XS-Leak-Klassen geführt.

Werte:

  • unsafe-none (Default) — alte Verhalten, Cross-Origin-Opener-Verbindung möglich.
  • same-origin-allow-popups — diese Seite verliert Opener-Connection nur zu Cross-Origin-Popups; eigene Popups bleiben verbunden.
  • same-origin — strikteste Variante; Opener-Connection zu Cross-Origin-Seiten ist gekappt.

Beispiel:

HTTP coop-same-origin.txt
Cross-Origin-Opener-Policy: same-origin

Wirkung: Cross-Origin-Tab, der via window.open() deine Seite geöffnet hat, kann nicht mehr auf window.opener zugreifen. Dieselbe Seite mit anderer Origin im Iframe — kein Zugriff.

Use-Case auch ohne Cross-Origin-Isolation: COOP alleine ist ein wertvoller Schutz gegen Tab-napping und window.opener-Manipulation. Auch ohne COEP empfehlenswert.

COEP — Cross-Origin-Embedder-Policy

Problem: Eingebettete Ressourcen (Bilder von fremden Domains, iframes mit Third-Party-Content) können in Spectre-Klassen ausgenutzt werden, um Cross-Origin-Daten zu leaken.

Werte:

  • unsafe-none (Default) — eingebettete Cross-Origin-Ressourcen sind okay ohne explizite Erlaubnis.
  • require-corp — Cross-Origin-Ressourcen MÜSSEN entweder mit CORP-Header zustimmen oder mit CORS-Header (für korrekt CORS-fetched).
  • credentialless — Cross-Origin-Requests gehen ohne Credentials raus (keine Cookies). Schwächere Variante, dafür weniger Migration nötig.

Wirkung von require-corp: wenn eine Cross-Origin-Resource keinen passenden CORP-Header sendet, blockt der Browser das Laden. Bilder, Skripte, Iframes von fremden Domains brechen — außer sie spielen mit.

HTTP coep-require-corp.txt
Cross-Origin-Embedder-Policy: require-corp

credentialless als pragmatische Alternative:

HTTP coep-credentialless.txt
Cross-Origin-Embedder-Policy: credentialless

Bei credentialless sendet der Browser Requests zu Cross-Origin-Ressourcen ohne Cookies/Credentials — dadurch ist Spectre-Leak von User-spezifischen Daten unmöglich, weil die Ressourcen Public-Versionen sind. Erfordert keine Server-Änderungen bei den Drittparteien. Weniger restriktiv, aber leichter zu deployen.

CORP — Cross-Origin-Resource-Policy

Problem: Eine Resource, die du auslieferst (Bild, JS-File, JSON), kann von beliebigen anderen Origins eingebunden werden — was historisch nicht problematisch war, mit Spectre aber zur Daten-Leak-Quelle wurde.

Werte:

  • same-origin — nur eigene Origin darf diese Ressource laden.
  • same-site — nur eigene Site darf laden (eigene Origin plus Subdomains). „Site" = registrierbares Schema-Domain-Paar.
  • cross-origin — beliebig (für absichtlich öffentliche Resources).

Beispiel — Avatare nur für eigene App:

HTTP corp-same-origin.txt
# /avatars/123.jpg
Cross-Origin-Resource-Policy: same-origin
# → nur eigene Origin darf das Bild laden

Beispiel — Public-API mit CORS:

HTTP corp-cross-origin.txt
Access-Control-Allow-Origin: *
Cross-Origin-Resource-Policy: cross-origin
# → bewusst öffentlich erlaubt

Default-Empfehlung: für eigene Resources Cross-Origin-Resource-Policy: same-origin (oder same-site bei Multi-Subdomain-App) — verhindert, dass fremde Sites deine Resources einbetten und für XS-Leak-Klassen nutzen.

Cross-Origin Isolation aktivieren

Mit beiden Headern setzt der Browser die Seite in „cross-origin isolated" mode:

HTTP coi-headers.txt
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Prüfung im JS:

JavaScript check-cross-origin-isolated.js
if (self.crossOriginIsolated) {
  console.log('Cross-Origin Isolation aktiv');
  // SharedArrayBuffer, performance.measureUserAgentSpecificMemory(), etc.
}

Was freigeschaltet wird:

  • SharedArrayBuffer — High-Performance-Worker-Kommunikation. Für WebAssembly-Apps und manche Game-Engines essentiell.
  • performance.now() mit hoher Auflösung (Mikrosekunden statt Millisekunden).
  • performance.measureUserAgentSpecificMemory() — Memory-Profiling.
  • Atomics.wait() und verwandte APIs.

Was Bedingung ist:

  • Alle Cross-Origin-Subresources (Bilder, Skripte, Fonts, iframes) müssen mit CORP oder CORS antworten.
  • Bestehende Apps haben dabei oft broken Drittparteien — Migrations-Aufwand.

Migrations-Pfad

Phase 1 — COOP allein:

Cross-Origin-Opener-Policy: same-origin ohne COEP. Wertvoller Schutz, kostenlos. Macht keine Drittpartei-Ressourcen kaputt. Mindeststandard für moderne Apps.

Phase 2 — CORP auf eigene Resources:

Pro Resource den korrekten CORP-Header setzen — same-origin für privat, cross-origin für absichtlich öffentliche. Bereitet Phase 3 vor.

Phase 3 — COEP mit Report-Only:

Cross-Origin-Embedder-Policy-Report-Only: require-corp testet, welche Drittpartei-Resources scheitern würden. Reporting-Endpoint sammelt die Violations.

Phase 4 — COEP enforce:

Wenn alle Drittparteien geklärt sind (CORS-fetched oder mit korrektem CORP), Header von Report-Only auf Enforce wechseln. Damit ist Cross-Origin Isolation aktiv.

Realistische Timeline: für eine App mit vielen Embeds (Werbung, Social Widgets, Maps, Videos) Monate. Für eine SPA mit eigenem Backend deutlich schneller.

credentialless als Workaround: Wenn Drittparteien keine CORP-Header setzen und nicht kontrollierbar sind, ist Cross-Origin-Embedder-Policy: credentialless der einfachere Migration-Pfad. Funktional fast gleich, Migration deutlich weniger schmerzhaft.

Reporting für COOP/COEP

Beide Header unterstützen Reporting-API:

HTTP coop-coep-reporting.txt
Reporting-Endpoints: isolation-endpoint="https://csp-report.example.com/isolation"
Cross-Origin-Opener-Policy: same-origin; report-to=isolation-endpoint
Cross-Origin-Embedder-Policy-Report-Only: require-corp; report-to=isolation-endpoint

Reports kommen für:

  • COOP-Violations — fremde Origin versucht via window.opener zuzugreifen.
  • COEP-Violations — Cross-Origin-Resource ohne CORP/CORS würde geblockt.

Die Reports zeigen pro Page genau, welche Embeds problematisch sind — Migration wird zielgerichtet.

Praktische Konfiguration

nginx:

Nginx nginx-coop-coep.conf
# Für HTML-Pages
location / {
    add_header Cross-Origin-Opener-Policy "same-origin" always;
    add_header Cross-Origin-Embedder-Policy "require-corp" always;
    # ...
}

# Für eigene Static-Resources
location /static/ {
    add_header Cross-Origin-Resource-Policy "same-origin" always;
    # ...
}

# Für Public-API
location /api/public/ {
    add_header Access-Control-Allow-Origin "*";
    add_header Cross-Origin-Resource-Policy "cross-origin" always;
    # ...
}

Express:

JavaScript express-coop-coep.js
import helmet from 'helmet';

app.use(helmet({
  crossOriginOpenerPolicy: { policy: 'same-origin' },
  crossOriginEmbedderPolicy: { policy: 'require-corp' },
  crossOriginResourcePolicy: { policy: 'same-origin' },
}));

// Pro Public-Endpoint überschreiben
app.get('/api/public/data', (req, res) => {
  res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
  // ...
});

Besonderheiten

SharedArrayBuffer war 2018 wegen Spectre temporär abgeschaltet

Vor Spectre war SharedArrayBuffer in allen Browsern verfügbar. Nach Disclosure wurde es 2018 deaktiviert, weil es Spectre-Side-Channels mit hoher Präzision ermöglichte. Wiedereinführung 2020 mit der Cross-Origin-Isolation-Anforderung — d. h. nur, wenn COOP+COEP gesetzt sind. Apps wie Google Earth (WebAssembly) und manche Bild-/Video-Editoren brauchen es zwingend.

popups mit COOP same-origin-allow-popups

Wenn deine App OAuth-Popups öffnet (klassisch: Login mit Google), brauchst du <code>same-origin-allow-popups</code> statt <code>same-origin</code> — sonst kann das Popup nach Auth nicht mehr mit deiner Page kommunizieren. Pragmatischer Default für die meisten Login-Flows.

credentialless als COEP-Variante seit Chrome 96

Die credentialless-Variante wurde Ende 2021 in Chrome eingeführt — Cross-Origin-Requests gehen ohne Credentials raus. Spectre-Schutz gleichwertig (Public-Variante der Ressource leakt keine User-Daten), aber Migration ohne CORP-Pflicht der Drittparteien. Stand 2026 von allen großen Browsern unterstützt.

window.opener.location ist die historische Tab-napping-Klasse

Vor COOP: ein Link mit target="_blank" öffnete eine neue Tab; die neue Tab konnte via window.opener.location = 'evil.com' die ursprüngliche Tab im Hintergrund umlenken. rel="noopener" auf <a>-Tags war Workaround. Moderner Browser-Default ist noopener für target="_blank". COOP ist die Server-seitige Garantie.

Spectre-V2 in 2023 — Side-Channels weiter relevant

Auch 2023 sind neue Spectre-Klassen-Varianten gefunden worden (Inception, RIDL-V2). Browser-Mitigations sind nicht perfekt — Cross-Origin-Isolation ist die strukturelle Antwort auf der Web-Ebene. Hardware-Mitigations folgen über CPU-Updates.

CORP für Static-CDN-Assets

Wenn die App Bilder/Fonts von cdn.example.com lädt, muss der CDN den passenden CORP-Header setzen — sonst werden die Assets bei COEP-aktivierter Seite geblockt. Cloudflare, Fastly und Akamai haben Header-Konfig-Optionen. AWS S3 unterstützt CORP via Bucket-Policy seit 2021.

Cross-Origin Isolation als Browser-Feature-Trigger

Manche Browser-Features brauchen aktive Cross-Origin Isolation: SharedArrayBuffer (alle), performance.measureUserAgentSpecificMemory() (Chrome 89+), high-resolution performance.now() (alle). Wer diese Features nutzt: COOP+COEP sind Pflicht, nicht optional.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Secure Headers & Cookies

Zur Übersicht