---
title: "COOP, COEP, CORP: przewodnik po cross-origin isolation (2026)"
description: "Kompletny przewodnik po Cross-Origin-Opener-Policy, Cross-Origin-Embedder-Policy i Cross-Origin-Resource-Policy. Dlaczego YouTube, Stripe i popupy OAuth przestają działać i jak to naprawić bez rezygnacji z izolacji."
date: 2026-04-19
category: Bezpieczeństwo
tags: ["Security", "COOP", "COEP", "CORP", "Cross-Origin", "HTTP Headers", "SharedArrayBuffer"]
url: https://uper.pl/blog/coop-coep-corp-cross-origin-isolation/
---

# COOP, COEP, CORP — kompletny przewodnik po cross-origin isolation, SharedArrayBuffer i typowych problemach z YouTube, Stripe i OAuth

Trzy nagłówki HTTP — **Cross-Origin-Opener-Policy (COOP)**, **Cross-Origin-Embedder-Policy (COEP)** i **Cross-Origin-Resource-Policy (CORP)** — wspólnie budują mechanizm zwany **cross-origin isolation**. Poprawnie skonfigurowane chronią stronę przed atakami typu Spectre i tabnappingiem oraz odblokowują `SharedArrayBuffer` i high-resolution timery. Źle skonfigurowane po cichu łamią osadzenia YouTube, checkout Stripe i logowanie Google. Ten przewodnik pokazuje, jak ustawić je dobrze.

## TL;DR — trzy nagłówki w 60 sekund

| Nagłówek | Co kontroluje | Kiedy go ustawiać |
|----------|---------------|-------------------|
| **COOP** | Czy inne okna/popupy mają dostęp do Twojego `window` | Zawsze — chroni przed tabnappingiem |
| **COEP** | Czy Twoja strona może ładować subresources bez deklaracji zgody | Tylko gdy potrzebujesz `SharedArrayBuffer` lub `crossOriginIsolated` |
| **CORP** | Kto może ładować Twoje zasoby (obrazy, skrypty) | Na zasobach, które hostujesz dla innych witryn |

Dla typowej witryny marketingowej / bloga wystarczy:

```http
Cross-Origin-Opener-Policy: same-origin-allow-popups
```

Dla aplikacji webowej wymagającej `SharedArrayBuffer` (WebAssembly wielowątkowy, FFmpeg.wasm, gry, edytory wideo):

```http
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```

## Dlaczego te nagłówki powstały

### Spectre (2018)

W styczniu 2018 opublikowano [lukę Spectre](https://spectreattack.com/) — atak side-channel wykorzystujący speculative execution w procesorach. Umożliwił on odczytywanie pamięci z innych procesów, w tym innych zakładek przeglądarki. Dla przeglądarek to była katastrofa: JavaScript z reklamowej ramki mógł teoretycznie odczytać hasła z innej zakładki.

Odpowiedzią było **Site Isolation** (Chrome) oraz docelowo **cross-origin isolation** na poziomie HTTP. Strony, które chcą mieć dostęp do precyzyjnych timerów i współdzielonej pamięci (`SharedArrayBuffer`), muszą udowodnić, że są izolowane od potencjalnie wrogich źródeł.

### Tabnapping i opener exploitation

Gdy otwierasz okno przez `<a target="_blank">` lub `window.open()`, nowe okno ma dostęp do `window.opener`. Bez ochrony ta referencja pozwala złośliwej stronie podmienić zawartość okna rodzica (`window.opener.location = 'phishing.com'`). To klasyczny **tabnapping**.

`rel="noopener"` w linkach rozwiązuje problem dla pojedynczych linków, ale **COOP rozwiązuje go na poziomie całej strony**, niezależnie od tego, jak otwarto okno. Nagłówki cross-origin to jeden z wielu warstw obrony — przypadki takie jak [atak na łańcuch dostaw wtyczek WordPress w 2026](/blog/atak-lancuch-dostaw-wtyczki-wordpress-2026/) pokazują, że bez strategii defense-in-depth pojedyncza luka potrafi otworzyć dostęp do setek tysięcy stron.

## COOP — Cross-Origin-Opener-Policy

COOP decyduje, **kto ma dostęp do Twojego obiektu `window`**. Trzy dopuszczalne wartości:

### `unsafe-none` (domyślna)

```http
Cross-Origin-Opener-Policy: unsafe-none
```

Brak izolacji. Dowolna strona, która Cię otworzy przez `window.open()`, zachowuje referencję `window.opener` i może ją wykorzystać. **Nie używaj na produkcji** — nawet jeśli nie korzystasz z popupów, zostawiasz otwarte drzwi dla tabnappingu.

### `same-origin-allow-popups` (zalecana dla większości stron)

```http
Cross-Origin-Opener-Policy: same-origin-allow-popups
```

- **Izolacja przychodząca:** strony innego originu otwierające Cię tracą dostęp do Twojego `window`.
- **Izolacja wychodząca:** popupy, które *Ty* otwierasz, zachowują normalną komunikację z opener-em.

To złoty środek. Chronisz się przed tabnappingiem, ale nie łamiesz popupów OAuth, udostępniania, payments itp. **Tego używamy na uper.pl.**

### `same-origin` (pełna izolacja)

```http
Cross-Origin-Opener-Policy: same-origin
```

Pełna izolacja w obie strony. Żadna strona innego originu nie ma dostępu do Twojego `window`, ani Ty do ich. To konieczne do osiągnięcia `crossOriginIsolated === true` i odblokowania `SharedArrayBuffer`.

**Cena:** popupy z innych originów otwierane z Twojej strony natychmiast tracą `window.opener`. To właśnie łamie YouTube, Stripe i logowanie Google.

### Tabela decyzyjna

| Typ strony | Zalecana wartość |
|------------|------------------|
| Strona marketingowa / blog | `same-origin-allow-popups` |
| SaaS z osadzeniami (YouTube, Stripe, Intercom) | `same-origin-allow-popups` |
| SPA z WebAssembly wielowątkowym | `same-origin` |
| Edytor wideo / gra w przeglądarce | `same-origin` |
| E-commerce z popupowym checkoutem | `same-origin-allow-popups` |

## COEP — Cross-Origin-Embedder-Policy

COEP wymusza, aby **wszystkie ładowane przez Twoją stronę zasoby** z innych originów **jawnie zgodziły się** być przez Ciebie osadzone. To druga połowa wymagania dla `crossOriginIsolated`.

### `unsafe-none` (domyślna)

Brak wymagań. Ładujesz cokolwiek, skądkolwiek.

### `require-corp`

```http
Cross-Origin-Embedder-Policy: require-corp
```

Każdy zasób cross-origin (obraz, skrypt, iframe) musi albo:
- Mieć nagłówek `Cross-Origin-Resource-Policy: cross-origin` (wyraźna zgoda), **albo**
- Być załadowany z CORS (`Access-Control-Allow-Origin`).

Inaczej przeglądarka zablokuje zasób. To rygorystyczne — **zepsuje większość integracji z CDN-ami i serwisami third-party, które nie ustawiają CORP/CORS**.

### `credentialless` (nowsze, 2022+)

```http
Cross-Origin-Embedder-Policy: credentialless
```

Luźniejsza wersja: zamiast wymagać CORP/CORS, przeglądarka po prostu ładuje zasoby bez cookies i innych credentials. Dla większości zastosowań (obrazy, fonty, publiczne API) to wystarczy, a wymaga znacznie mniej zmian po stronie zewnętrznych dostawców.

**Wsparcie przeglądarek:** Chrome 96+, Firefox 119+. Safari dołączyło dopiero w 2024 — jeśli obsługujesz starsze iOS, miej fallback.

## CORP — Cross-Origin-Resource-Policy

Odwrotna perspektywa. Jeśli **Ty hostujesz zasoby** (CDN, API obrazków, fonty dla innych witryn), CORP mówi przeglądarce **kto może je ładować**.

### Wartości

```http
Cross-Origin-Resource-Policy: same-origin      # tylko Twoja domena
Cross-Origin-Resource-Policy: same-site        # Twoja domena i subdomeny
Cross-Origin-Resource-Policy: cross-origin     # dowolna strona
```

### Kiedy którą ustawiać

- **`same-origin`** — zasoby prywatne (API zwracające dane użytkownika, obrazy z pulpitu).
- **`same-site`** — zasoby współdzielone między subdomenami (logo na `app.example.com` i `www.example.com`).
- **`cross-origin`** — publiczne zasoby, które *chcesz*, żeby inni osadzali (obrazki dla embedów, publiczne fonty, avatar CDN).

Jeśli jesteś dostawcą API i Twoi klienci narzekają, że ich strony z COEP przestały ładować Twoje obrazy — brakuje Ci `Cross-Origin-Resource-Policy: cross-origin`.

## Magiczna flaga: self.crossOriginIsolated

Gdy jednocześnie ustawisz:

```http
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```

w JavaScripcie dostajesz:

```js
self.crossOriginIsolated === true
```

Co to odblokowuje:

- **`SharedArrayBuffer`** — współdzielona pamięć między wątkami (Web Workers). Niezbędne dla wielowątkowego WebAssembly, FFmpeg.wasm, Three.js z Web Workers, emulatorów. Uwaga: pełna izolacja potrafi pogorszyć [LCP](/blog/lcp-optimization-guide/), bo zasoby third-party wymagają dodatkowych nagłówków CORP/CORS i w razie ich braku są blokowane — co realnie spowalnia pierwsze renderowanie.
- **`performance.measureUserAgentSpecificMemory()`** — precyzyjny pomiar zużycia pamięci.
- **High-resolution timers** — `performance.now()` bez celowego rozmywania (mitigacja Spectre).
- **`Atomics.wait()`** w głównym wątku.

Dla typowej witryny marketingowej to wszystko nie ma znaczenia. Dla aplikacji WebAssembly — kluczowe.

## Realne problemy i rozwiązania

### YouTube embed przestał działać

**Objaw:** wideo się renderuje, ale klikanie "Udostępnij", logowanie, pełny ekran w niektórych przeglądarkach nie działa.

**Przyczyna:** masz ustawione `Cross-Origin-Opener-Policy: same-origin`. Player YouTube otwiera popupy, które natychmiast tracą referencję do swojego opener-a.

**Rozwiązanie:** zmień na `same-origin-allow-popups`. Jeśli potrzebujesz `crossOriginIsolated` (np. dla WASM), wyniesienie YouTube do osobnej strony bez izolacji.

### Stripe Checkout popup nie zamyka się po płatności

**Objaw:** użytkownik płaci, popup pozostaje otwarty, Twoja strona nie wie, że transakcja się powiodła.

**Przyczyna:** Stripe po zakończeniu wywołuje `window.opener.postMessage()` do Twojej strony. Z `COOP: same-origin` referencja jest `null`.

**Rozwiązanie:** `same-origin-allow-popups` lub użycie [Stripe Elements](https://stripe.com/docs/payments/elements) zamiast Checkout (renderuje się w Twoim iframe, nie popup).

### Google Sign-In / OAuth callback nie dochodzi

**Objaw:** użytkownik loguje się w popupie Google, popup się zamyka, ale Twoja aplikacja nie dostaje tokena.

**Przyczyna:** identyczna jak Stripe — `postMessage` z popupa trafia do `null`-owego opener-a.

**Rozwiązanie:** `same-origin-allow-popups`. Alternatywnie — użyj Google Identity Services (GIS) z FedCM, który używa dedykowanego API zamiast popupów.

### Obrazy z CDN się nie ładują po włączeniu COEP

**Objaw:** po dodaniu `COEP: require-corp` wszystkie obrazki z zewnętrznego CDN (Cloudinary, imgix, Gravatar) się nie ładują.

**Przyczyna:** CDN nie zwraca nagłówka `Cross-Origin-Resource-Policy: cross-origin`.

**Rozwiązania:**
1. Skonfiguruj CDN, aby dodał `Cross-Origin-Resource-Policy: cross-origin` do odpowiedzi (większość ma taką opcję).
2. Załaduj obrazki z `crossorigin="anonymous"` i upewnij się, że CDN zwraca `Access-Control-Allow-Origin: *`.
3. Użyj luźniejszego `COEP: credentialless` zamiast `require-corp`.

### Social sharing popup (Twitter/LinkedIn) po otwarciu nie odpowiada

**Objaw:** popup "Share on Twitter" otwiera się, ale interakcje w nim są dziwne / crashują.

**Przyczyna:** `COOP: same-origin` na Twojej stronie.

**Rozwiązanie:** `same-origin-allow-popups`.

## Jak debugować

### 1. Sprawdź status izolacji

W konsoli DevTools:

```js
self.crossOriginIsolated
// true  = masz pełną izolację
// false = nie masz
```

### 2. DevTools → Application → Frames

Chrome DevTools → zakładka **Application** → sekcja **Frames** → kliknij swoją stronę. Zobaczysz:

- `Cross-Origin Isolated: yes/no`
- Dokładne wartości COOP, COEP, CORP
- Listę sub-frames i ich status izolacji

### 3. Reporty naruszeń

Możesz dostawać raporty naruszeń COOP:

```http
Cross-Origin-Opener-Policy: same-origin; report-to="coop-endpoint"
Reporting-Endpoints: coop-endpoint="https://twojadomena.pl/coop-report"
```

Dostaniesz JSON z informacją, która ramka próbowała coś zrobić i została zablokowana. Kluczowe przy diagnozie cichych awarii.

### 4. Konsola przeglądarki

COEP blokady pojawiają się w konsoli jako:

```
A resource is blocked by OpaqueResponseBlocking, please check browser console for details.

Failed to load resource: net::ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep
```

## Gotowe konfiguracje

### Witryna marketingowa / blog (rekomendowane)

```http
Cross-Origin-Opener-Policy: same-origin-allow-popups
Cross-Origin-Resource-Policy: same-site
```

Bez COEP. Daje ochronę przed tabnappingiem, nie łamie żadnych integracji.

### E-commerce z zewnętrznym checkoutem

```http
Cross-Origin-Opener-Policy: same-origin-allow-popups
Cross-Origin-Resource-Policy: same-site
```

Identyczna. Kluczowe — *nie* używać `same-origin`, bo zabije Stripe/PayPal popupy.

### SPA z WebAssembly (SharedArrayBuffer)

```http
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: same-origin
```

Plus: każdy zewnętrzny zasób (CDN, fonty, obrazki) musi mieć `Cross-Origin-Resource-Policy: cross-origin` lub CORS.

### Aplikacja publicznego API / CDN

```http
Cross-Origin-Resource-Policy: cross-origin
```

Tylko to. Mówisz światu: "możecie mnie używać, nawet z izolowanych stron".

## Interakcja z innymi nagłówkami

- **CSP** — ortogonalny. CSP kontroluje co ładujesz, COOP/COEP kontrolują warunki izolacji. [Zobacz przewodnik po CSP dla usług Google](/blog/csp-google-services/).
- **X-Frame-Options** — dotyczy tego, czy *Ty* możesz być osadzony w iframe. Inna kategoria niż COOP.
- **Referrer-Policy** — niezwiązany.
- **HSTS** — niezwiązany. Zobacz [kompletny przewodnik po nagłówkach HTTP](/blog/naglowki-bezpieczenstwa-http/).

<FaqBlog
  questions={[
    {
      question: 'Co oznacza same-origin-allow-popups w Cross-Origin-Opener-Policy?',
      answer: 'To wartość <code>COOP</code>, która izoluje Twoją stronę od okien <strong>przychodzących</strong> z innych originów (ochrona przed tabnappingiem), ale pozwala popupom, które <em>Ty</em> otwierasz, zachować komunikację z Twoją stroną. To najlepsza wartość dla większości witryn marketingowych i aplikacji używających integracji third-party (YouTube, Stripe, logowanie Google).'
    },
    {
      question: 'Dlaczego YouTube embed przestał działać po włączeniu COOP?',
      answer: 'Prawdopodobnie ustawiłeś <code>Cross-Origin-Opener-Policy: same-origin</code> (pełna izolacja). Player YouTube otwiera popupy (Udostępnij, logowanie, pełny ekran), które przy pełnej izolacji tracą referencję do Twojej strony i komunikacja między nimi zawodzi. Zmień wartość na <code>same-origin-allow-popups</code> — zachowasz ochronę przed tabnappingiem, a YouTube znów będzie działał.'
    },
    {
      question: 'Jak włączyć SharedArrayBuffer w przeglądarce?',
      answer: 'Musisz osiągnąć stan <code>crossOriginIsolated === true</code>. Wymaga to jednoczesnego ustawienia dwóch nagłówków HTTP: <code>Cross-Origin-Opener-Policy: same-origin</code> oraz <code>Cross-Origin-Embedder-Policy: require-corp</code>. Dodatkowo każdy zasób cross-origin, który ładujesz (obrazki, skrypty, fonty), musi mieć nagłówek <code>Cross-Origin-Resource-Policy: cross-origin</code> lub być załadowany z CORS.'
    },
    {
      question: 'Jaka jest różnica między COOP, COEP i CORP?',
      answer: '<strong>COOP</strong> (Cross-Origin-Opener-Policy) chroni Twoje <code>window</code> przed innymi stronami — dotyczy izolacji zakładek i popupów. <strong>COEP</strong> (Cross-Origin-Embedder-Policy) wymusza, aby zasoby, które <em>Ty ładujesz</em> z innych originów, jawnie wyraziły zgodę. <strong>CORP</strong> (Cross-Origin-Resource-Policy) to odwrotność COEP — wysyłasz go na zasobach, które <em>Ty hostujesz</em>, aby powiedzieć przeglądarce, kto może je ładować.'
    },
    {
      question: 'Czy zwykła strona z blogiem potrzebuje COEP i CORP?',
      answer: 'Nie. Dla typowej strony marketingowej, bloga czy sklepu wystarczy <code>Cross-Origin-Opener-Policy: same-origin-allow-popups</code>. COEP i CORP są potrzebne dopiero, gdy Twoja aplikacja używa <code>SharedArrayBuffer</code>, wielowątkowego WebAssembly, albo hostujesz publiczne zasoby dla innych witryn.'
    },
    {
      question: 'Co zrobić, gdy CDN z obrazkami blokuje się po włączeniu COEP?',
      answer: 'Trzy rozwiązania: (1) skonfiguruj CDN, aby dodawał <code>Cross-Origin-Resource-Policy: cross-origin</code> do odpowiedzi — większość CDN-ów ma taką opcję; (2) ładuj obrazki z atrybutem <code>crossorigin="anonymous"</code> i upewnij się, że CDN zwraca <code>Access-Control-Allow-Origin: *</code>; (3) użyj luźniejszej wartości <code>Cross-Origin-Embedder-Policy: credentialless</code> zamiast <code>require-corp</code> — nie wymaga zmian po stronie dostawców.'
    },
    {
      question: 'Czy ustawienie COOP łamie Google Analytics lub Google Tag Manager?',
      answer: 'Nie. GA4 i GTM komunikują się przez fetch/XHR, nie przez popupy, więc żadna wartość COOP ich nie rozbija. Problemy pojawiają się dopiero przy interakcjach otwierających nowe okna: logowanie przez Google, Stripe Checkout, udostępnianie w social media. Zobacz też <a href="/blog/csp-google-services/">przewodnik po CSP dla usług Google</a>.'
    },
    {
      question: 'Czym jest credentialless w Cross-Origin-Embedder-Policy?',
      answer: 'To nowsza, luźniejsza wartość COEP (Chrome 96+, Firefox 119+, Safari 2024+). Zamiast wymagać, aby zewnętrzne zasoby wyraziły zgodę przez CORP lub CORS, przeglądarka po prostu ładuje je <em>bez cookies i innych credentials</em>. Dla publicznych zasobów (obrazki, fonty, publiczne API) to w zupełności wystarczy, a wymaga znacznie mniej zmian po stronie dostawców zewnętrznych.'
    }
  ]}
  heading="Najczęściej zadawane pytania o COOP, COEP i CORP"
  id="faq"
/>

## Sprawdź cross-origin isolation z UPER SEO Auditor

Diagnozowanie cichych awarii COOP/COEP jest uciążliwe — objawy to dziwne zachowanie popupów i zepsuty OAuth, a nie czytelne komunikaty błędów. Zakładka Security w **[UPER SEO Auditor](https://chromewebstore.google.com/detail/uper-seo-auditor/khhpbeckpphaoiemjdijhbfpjnendage)** (wtyczka Chrome) pokazuje wszystkie trzy nagłówki dla aktualnej strony:

- **Cross-Origin-Opener-Policy** — aktualna wartość i czy pasuje do rozsądnego defaulta
- **Cross-Origin-Embedder-Policy** — wykryta lub brakująca, łącznie z obsługą `credentialless`
- **Cross-Origin-Resource-Policy** — dla zasobów, które sama strona serwuje

Wszystkie trzy są wliczane do ważonego scoringu 0-10 razem z HSTS, CSP, X-Frame-Options, Referrer-Policy i Permissions-Policy. Zainstaluj wtyczkę, otwórz zakładkę Security i zobaczysz realne produkcyjne nagłówki bez sięgania do terminala.

## Podsumowanie

Dla 95% witryn jedyny nagłówek z tej trójki, którego potrzebujesz, to:

```http
Cross-Origin-Opener-Policy: same-origin-allow-popups
```

Chroni przed tabnappingiem, nie łamie niczego. COEP i CORP są potrzebne tylko, gdy hostujesz zasoby dla innych lub Twoja aplikacja używa `SharedArrayBuffer`.

Jeśli już masz wdrożone pełne izolowanie (`same-origin` + `require-corp`) i nagle zauważasz ciche awarie popupów — wróć do `same-origin-allow-popups`. Cena w bezpieczeństwie jest minimalna, cena w funkcjonalności gigantyczna.

## Źródła

- [MDN — Cross-Origin-Opener-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy)
- [MDN — Cross-Origin-Embedder-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy)
- [MDN — Cross-Origin-Resource-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy)
- [web.dev — Cross-Origin Isolation](https://web.dev/articles/cross-origin-isolation-guide)
- [Chrome Platform — COEP: credentialless](https://developer.chrome.com/blog/coep-credentialless-origin-trial/)
- [Spectre Attack — whitepaper](https://spectreattack.com/)
