StackBlitz Embed — Cross-Origin Isolation Issue
Summary
@stackblitz/sdk.embedProject() fails with "Unable to run Embedded Project — Looks like this project is being embedded without proper isolation headers" even when the embedding page correctly sends all required COOP/COEP headers.
Environment
|
|
| SDK version |
@stackblitz/sdk@1.11.0 |
| Browser |
Chrome (latest) |
| Embed method |
sdk.embedProject() (POST via form → /run endpoint) |
| Template |
node (WebContainers) |
| Headers tested |
Both require-corp and credentialless |
What Works
sdk.openProject({ newWindow: true }) — Opens StackBlitz in a new tab → runs correctly ✅
sdk.embedProject() with crossOriginIsolated: true but WITHOUT COOP/COEP on parent → connection refused (iframe can't load at all)
- Parent page isolation —
window.crossOriginIsolated is true on the embedding page with either COEP value
Root Cause
The Problem
When crossOriginIsolated: true is passed to sdk.embedProject(), the SDK:
- Adds
cross-origin-isolated to the iframe's allow attribute
- Adds
corp=1 query parameter to the embed URL: https://stackblitz.com/run?corp=1&embed=1&...
The corp=1 parameter tells StackBlitz's server to serve the page with Cross-Origin-Embedder-Policy: require-corp (strict mode).
However, StackBlitz's own page loads cross-origin resources that lack Cross-Origin-Resource-Policy headers:
GET https://cdn.segment.com/analytics.js/v1/.../analytics.min.js
→ ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep
POST https://www.google.com/ccm/collect?...
→ ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep
GET https://json.schemastore.org/prettierrc
→ CORS error (No 'Access-Control-Allow-Origin' header)
GET https://json.schemastore.org/package
→ CORS error (No 'Access-Control-Allow-Origin' header)
GET https://json.schemastore.org/tsconfig
→ CORS error (No 'Access-Control-Allow-Origin' header)
These blocked resources prevent the WebContainer from initializing properly.
The Catch-22
| Scenario |
Result |
crossOriginIsolated: true + corp=1 |
StackBlitz serves COEP → its analytics/CDN resources blocked → WebContainer fails |
crossOriginIsolated: false |
StackBlitz serves NO COEP → resources load fine → but WebContainer can't use SharedArrayBuffer |
Console Errors
All from inside the StackBlitz iframe (cross-origin, stackblitz.com):
run:38 GET https://cdn.segment.com/analytics.js/v1/.../analytics.min.js
net::ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep
run:213 POST https://www.google.com/ccm/collect?...
net::ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep
run:1 Access to fetch at 'https://json.schemastore.org/prettierrc'
blocked by CORS policy (No 'Access-Control-Allow-Origin' header)
run:1 Access to fetch at 'https://json.schemastore.org/package'
blocked by CORS policy
run:1 Access to fetch at 'https://json.schemastore.org/tsconfig'
blocked by CORS policy
Embedding Page Headers Tested
Both combinations were tested on the embedding page (Vite dev server via server.headers):
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp # ❌ Same error
Cross-Origin-Embedder-Policy: credentialless # ❌ Same error
In both cases, window.crossOriginIsolated === true on the embedding page.
SDK Internals (v1.11.0)
Relevant code from @stackblitz/sdk/bundles/sdk.js:
// URL param generator (line 35)
crossOriginIsolated: (value) => trueParam("corp", value)
// Iframe allow attribute (lines 133-140)
function setFrameAllowList(target, frame, options = {}) {
const allowList = target.allow?.split(";")?.map((key) => key.trim()) ?? [];
if (options.crossOriginIsolated && !allowList.includes("cross-origin-isolated")) {
allowList.push("cross-origin-isolated");
}
if (allowList.length > 0) {
frame.allow = allowList.join("; ");
}
}
The embed flow:
embedProject() creates an iframe
- Writes an HTML form via
frame.contentDocument.write(html)
- Form auto-submits via POST to
https://stackblitz.com/run?corp=1&embed=1&...
- StackBlitz creates project and redirects (redirect may/may not preserve
corp=1)
- Connection established via
MessageChannel / postMessage
Related StackBlitz Issues
- #2045 — Cross-origin isolation
- #1739 — Embed isolation
- #400 — SharedArrayBuffer
- #5925 — WebContainer isolation
- #296 — Firefox limitation
Suggested Fix (StackBlitz-side)
StackBlitz should either:
- Serve its own page with
Cross-Origin-Embedder-Policy: credentialless instead of require-corp when corp=1 is present — this preserves window.crossOriginIsolated = true without blocking its own analytics/CDN resources.
- Add proper
Cross-Origin-Resource-Policy: cross-origin headers to its CDN resources (segment.com, Google Tag Manager, schemastore.org).
- Provide an SDK option to control the COEP mode (
require-corp vs credentialless).
Workaround
For now, use sdk.openProject({ newWindow: true }) instead of sdk.embedProject() — opens StackBlitz in a new tab where cross-origin isolation is not required.

StackBlitz Embed — Cross-Origin Isolation Issue
Summary
@stackblitz/sdk.embedProject()fails with "Unable to run Embedded Project — Looks like this project is being embedded without proper isolation headers" even when the embedding page correctly sends all required COOP/COEP headers.Environment
@stackblitz/sdk@1.11.0sdk.embedProject()(POST via form →/runendpoint)node(WebContainers)require-corpandcredentiallessWhat Works
sdk.openProject({ newWindow: true })— Opens StackBlitz in a new tab → runs correctly ✅sdk.embedProject()withcrossOriginIsolated: truebut WITHOUT COOP/COEP on parent → connection refused (iframe can't load at all)window.crossOriginIsolatedistrueon the embedding page with either COEP valueRoot Cause
The Problem
When
crossOriginIsolated: trueis passed tosdk.embedProject(), the SDK:cross-origin-isolatedto the iframe'sallowattributecorp=1query parameter to the embed URL:https://stackblitz.com/run?corp=1&embed=1&...The
corp=1parameter tells StackBlitz's server to serve the page withCross-Origin-Embedder-Policy: require-corp(strict mode).However, StackBlitz's own page loads cross-origin resources that lack
Cross-Origin-Resource-Policyheaders:These blocked resources prevent the WebContainer from initializing properly.
The Catch-22
crossOriginIsolated: true+corp=1crossOriginIsolated: falseConsole Errors
All from inside the StackBlitz iframe (cross-origin,
stackblitz.com):Embedding Page Headers Tested
Both combinations were tested on the embedding page (Vite dev server via
server.headers):In both cases,
window.crossOriginIsolated === trueon the embedding page.SDK Internals (v1.11.0)
Relevant code from
@stackblitz/sdk/bundles/sdk.js:The embed flow:
embedProject()creates an iframeframe.contentDocument.write(html)https://stackblitz.com/run?corp=1&embed=1&...corp=1)MessageChannel/postMessageRelated StackBlitz Issues
Suggested Fix (StackBlitz-side)
StackBlitz should either:
Cross-Origin-Embedder-Policy: credentiallessinstead ofrequire-corpwhencorp=1is present — this preserveswindow.crossOriginIsolated = truewithout blocking its own analytics/CDN resources.Cross-Origin-Resource-Policy: cross-originheaders to its CDN resources (segment.com, Google Tag Manager, schemastore.org).require-corpvscredentialless).Workaround
For now, use
sdk.openProject({ newWindow: true })instead ofsdk.embedProject()— opens StackBlitz in a new tab where cross-origin isolation is not required.