Before talking about headers, you need to understand the problem they were created to solve.
The Real Problem: What Is Spectre?
Spectre is a class of security vulnerabilities discovered in 2018 that affects modern CPUs, not just browsers.
In simple terms:
- CPUs try to be fast by guessing which code will run next
- This is called speculative execution
- An attacker can abuse this behavior to read memory they should never access
In the browser world, this means:
A malicious website could potentially infer data from another website opened in the same browser.
Passwords, tokens, private data — all at risk.
Browsers needed a strong isolation model, not just “best effort” sandboxing.
The Solution: Cross-Origin Isolation
Browsers introduced a concept called cross-origin isolation.
Goal: Make sure one website cannot observe or interact with another website’s memory or execution environment.
To enforce this, browsers added three new security headers:
- COOP
- COEP
- CORP
They work together, not separately.
COOP: Cross-Origin-Opener-Policy
What it is: COOP controls how your page relates to other tabs or windows.
What Problem It Solves
Without COOP:
- Two tabs from different origins can share a browser process
-
They can indirectly reference each other via
window.opener
With COOP:
- Your site gets its own browsing context
- Other origins are fully separated
Example:
httpCross-Origin-Opener-Policy: same-origin
What This Means
- Only pages from the same origin can share a window context
- Prevents tab-nabbing
- Required for strong memory isolation
COEP: Cross-Origin-Embedder-Policy
What it is: COEP controls which external resources your page is allowed to load.
The Core Idea
If you want strong isolation, you must be strict about embeds.
httpCross-Origin-Embedder-Policy: require-corp
What This Does
- Blocks cross-origin resources by default
-
Allows them only if:
- They send a CORP header, or
- They use CORS correctly
Why Browsers Enforce This
If arbitrary third-party resources could be embedded, isolation would be meaningless.
CORP: Cross-Origin-Resource-Policy
What it is: CORP is a header sent by the resource itself, not the embedding page.
It tells browsers:
“Who is allowed to load this resource?”
Example:
httpCross-Origin-Resource-Policy: same-origin
Common Values
| Value | Meaning |
|---|---|
same-origin |
Only this origin can load it |
same-site |
Subdomains allowed |
cross-origin |
Anyone can load it |
This is how CDNs and asset servers opt-in to COEP-protected pages.
How COOP, COEP, and CORP Work Together
Here’s the clean mental model:
- COOP → isolates browser windows and processes
- COEP → blocks unsafe embedded resources
- CORP → lets resources declare who can use them
Full Cross-Origin Isolation Setup
httpCross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
And assets respond with:
httpCross-Origin-Resource-Policy: same-origin
When all three align, the browser guarantees:
- Strong memory isolation
- Protection against Spectre-style attacks
Why Enabling These Headers Often Breaks Sites
This is where most devs get burned.
Common breakages:
- Google Fonts
- Analytics scripts
- CDN images
- Ads and iframes
Why? Because those resources don’t send CORP or CORS headers.
Typical Fixes
- Self-host fonts and scripts
- Use COEP-compatible CDNs
- Proxy third-party assets
- Or don’t enable COEP unless you need it
When You Actually Need COOP and COEP
You need them if you use:
-
SharedArrayBuffer - WebAssembly threads
- Browser-based games
- Audio / video processing
- High-performance web apps
You don’t need them for:
- Blogs
- Landing pages
- Marketing sites
Isolation has a cost.
Example: Nginx Configuration
nginxadd_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
For static assets:
nginxadd_header Cross-Origin-Resource-Policy "same-origin";
Final Takeaway
COOP, COEP, and CORP are not optional “security extras”. They are the browser’s answer to hardware-level vulnerabilities like Spectre.
If you’re building serious, performance-heavy web apps, you design with them in mind. If not, don’t enable them blindly.
Album of the blog:




