Cross-Origin-Embedder-Policy: require-corp vs credentialless (tested)
COEP controls which cross-origin resources a page may embed. Together with COOP same-origin it makes the page cross-origin isolated, which is what unlocks SharedArrayBuffer. We measured both halves.
1. When is the page cross-origin isolated?
| COOP ↓ / COEP → | (none) | require-corp | credentialless |
|---|---|---|---|
| (none) | false / undefined | false / undefined | false / undefined |
same-origin | false / undefined | true / function | true / function |
Values are self.crossOriginIsolated / typeof SharedArrayBuffer. You need both headers: COEP alone did nothing visible to script, and neither did COOP same-origin alone. Both COEP values worked equally for isolation.
2. What COEP blocked
| Cross-origin resource | No COEP | require-corp | credentialless |
|---|---|---|---|
<img>, no CORP header | loaded | blocked | loaded |
<img>, CORP: cross-origin | loaded | loaded | loaded |
<img crossorigin> + Access-Control-Allow-Origin: * | loaded | loaded | loaded |
<img crossorigin>, no ACAO | blocked (CORS) | blocked (CORS) | blocked (CORS) |
<iframe>, framed page sends nothing | loaded | blocked | blocked |
<iframe>, framed page sends COEP only (either value) | loaded | blocked | blocked |
<iframe>, framed page sends COEP: require-corp + CORP: cross-origin | loaded | loaded | loaded |
<iframe credentialless>, framed page sends nothing | loaded | loaded | loaded |
- The
require-corpimage block showed in the console asnet::ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep: with no CORP header, COEP treats the response as if it saidsame-origin. credentiallesslet the CORP-less image through. Per the spec it does this by sending no-cors cross-origin requests without cookies, so the image you get is the logged-out version (we checked loading, not cookie stripping).- Iframes were stricter than we expected: under either COEP value a cross-origin frame needed both its own COEP and
CORP: cross-origin. A blocked frame becamechrome-error://chromewebdata/with no console message on the parent page. Thecredentiallessattribute on the<iframe>was the only way to embed a frame that sends nothing. - Our two origins were also cross-site, so
CORP: same-siteon the image was blocked even without COEP (ERR_BLOCKED_BY_RESPONSE.NotSameSite); see CORP same-site vs cross-origin.
3. nginx
# the page that needs SharedArrayBuffer
add_header Cross-Origin-Opener-Policy same-origin always;
add_header Cross-Origin-Embedder-Policy credentialless always; # or require-corp
# on assets/frames you serve to that page from another origin
add_header Cross-Origin-Resource-Policy cross-origin always;
add_header Cross-Origin-Embedder-Policy require-corp always; # only needed on framed HTML
Start with credentialless if you embed third-party images you can't add headers to; use require-corp if you control every cross-origin resource or need cookies on them. Support for credentialless outside Chromium varies by browser and version (doc-based, check MDN); we only tested Chrome. Build the full header set in the free security headers generator.
Frequently asked questions
Why is crossOriginIsolated false?
In our Chrome test it was true only with both Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy (require-corp or credentialless). Either header alone left it false and SharedArrayBuffer undefined.
What is the difference between COEP require-corp and credentialless?
require-corp blocked a cross-origin image without a CORP header; credentialless loaded it (per the spec, without cookies). Both blocked cross-origin iframes that lacked COEP plus CORP: cross-origin, and both gave crossOriginIsolated true with COOP same-origin.
What does ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep mean?
Your page sends COEP require-corp and a cross-origin resource has no Cross-Origin-Resource-Policy header, so it is treated as same-origin only and blocked. Add CORP: cross-origin on that resource, load it with crossorigin plus CORS headers, or switch to COEP credentialless.
Why is my cross-origin iframe blocked under COEP?
In our test the framed page needed both its own COEP header and Cross-Origin-Resource-Policy: cross-origin. If you can't change it, the iframe credentialless attribute loaded it in Chrome.
Do Firefox and Safari support COEP credentialless?
We did not test them. According to MDN, support differs by browser and version; check current compatibility data and fall back to require-corp if you need it everywhere.
Written with AI assistance. Measured on 2026-10-01 in Chromium 153 (full build), fresh context per row: a page on localhost:8961 sent each COOP/COEP combination and we read self.crossOriginIsolated and typeof SharedArrayBuffer; under each COEP value it then loaded an image and an iframe from 127.0.0.1:8962 (cross-origin and cross-site) with varying CORP, ACAO and COEP headers. Firefox and Safari were not tested; remarks about them are from MDN, not this test. PlainHeaders is our extension; the other methods are free.