Notes · Dissecting Real Systems
growing
Nobody Shares Your Address Space
COOP, COEP and CORP are presented as three related headers. They are three doors into one process — and Spectre is why the browser cares who is inside it, not just what they are allowed to read.
These attacks challenge a fundamental assumption made by prior web browser architectures: that software-based isolation can keep sensitive data protected within an operating system process, despite running untrustworthy code within that process.
— Charles Reis, Alexander Moshchuk, Nasko Oskov, Site Isolation: Process Separation for Web Sites within the Browser (USENIX Security, 2019)
Cite this
Mangalapilly, Y. J. (2026, August). Nobody Shares Your Address Space. Saṃhitā Notes. https://yesudeep.com/blog/nobody-shares-your-address-space/ @online{mangalapilly2026nobody,
author = {Yesudeep Jose Mangalapilly},
title = {Nobody Shares Your Address Space},
journal = {Sa\d{m}hit\=a Notes},
year = {2026},
month = {August},
url = {https://yesudeep.com/blog/nobody-shares-your-address-space/},
urldate = {2026-08-12},
} Yesudeep Jose Mangalapilly. “Nobody Shares Your Address Space.” Saṃhitā Notes, 2026. https://yesudeep.com/blog/nobody-shares-your-address-space/. TY - ELEC
AU - Mangalapilly, Yesudeep Jose
TI - Nobody Shares Your Address Space
T2 - Saṃhitā Notes
PY - 2026
UR - https://yesudeep.com/blog/nobody-shares-your-address-space/
Y2 - 2026-08-12
ER - Three headers, one property, and the hardware bug underneath all of it. Spectre turns CPU speculation into a cross-origin read channel, underneath the same-origin checks the platform was built on. By the end you'll know what each of COOP, COEP and CORP actually does, why crossOriginIsolated is a conjunction that no single header can express, what the browser gives you in return, why fewer than one site in a hundred has it, and which widely-repeated advice about these headers is simply wrong.
Start with the assumption that broke.
The same-origin policy is an access-control rule: a document from one origin may not read the contents of a document, or the pixels of an image, from another. For most of the web's history this was enough, and it permitted a convenient implementation — several origins could live in one browser process, because the policy stood between them. Their bytes were adjacent in memory. The rule was what kept them apart.
Spectre made that arrangement untenable. Out-of-order processors execute speculatively — running ahead down a predicted branch and discarding the work if the prediction was wrong — but the discarded work leaves traces in the cache, and traces can be timed. The paper's own summary of the consequence is blunt: speculative execution implementations "violate the security assumptions underpinning numerous software security mechanisms, including operating system process separation, containerization, just-in-time (JIT) compilation."
Speculative execution — the processor guesses which way a branch will go and starts work on the guess before the answer is known, discarding it if wrong. The discarded work is architecturally invisible but leaves microarchitectural traces, such as which memory is now cached — and those can be measured. Learn more.
The web-specific result is the one that matters here, and the authors state it plainly: "we show a JavaScript program that successfully reads data from the address space of the browser process running it."
The same-origin policy said you may not read this. Spectre made reading possible without asking. The rule did not fail — it stopped being the thing that mattered.
Read the Site Isolation paper's threat model and you can watch the browser vendors absorb this. They introduce a memory disclosure attacker who "cannot run arbitrary code or lie to the browser process, but who can disclose arbitrary data within a renderer process's address space, even when the SOP would disallow it" — and note, devastatingly, that such an attacker is "not dependent on any bugs in web browser code."
There is no patch for that. If the attacker can read anything in the process and needs no bug to do it, the only remaining defense is to not have the data in the process. Which turns a question of permissions into a question of residency.
Imagine an office where every company's files sit in one big room, and the rule is simply that you only open your own filing cabinet. It works as long as everyone follows the rule.
Then someone discovers that by watching how long a cabinet takes to open, you can work out what is inside without opening it. The rule is intact — nobody opened anyone else's cabinet — and the information leaked anyway.
At that point "please only open your own" stops being a security policy. The only fix is separate rooms. And since the building cannot tell which files belong together, everyone has to declare it.
The browser's answer was Site Isolation — putting different sites in different processes — at a measured cost of "9-13% memory overhead" and "less than 2.25%" added page-load latency. But process separation only helps if the browser knows what is allowed to share a process, and a page that deliberately embeds another origin's image has, in effect, asked for co-residency. Hence the headers: the browser needs everything in an address space to have agreed to be there.
The HTML Standard says this in one line — the headers "are more about ensuring that everything in the same address space opts in to being there."
Three doors into one process
COEP — everything here opted in
Cross-Origin-Embedder-Policy: require-corp says: every no-cors subresource this document loads must explicitly declare that it is willing to be embedded.
The mechanism is worth getting exactly right, because the usual description is subtly wrong. COEP does not add a new check. It changes a default. The Fetch Standard's internal check runs like this: if the resource declared no policy, then switch on the embedder policy — under unsafe-none, "do nothing"; under require-corp, "set policy to same-origin."
COEP does not add a check. It replaces a default — flipping the absent-header case from allow to same-origin, which for a cross-origin resource means refuse.
That is deny-by-default implemented as a one-line substitution of a default value, and it is exactly the shape the last piece in this series argues for.
CORP — how a resource says yes
Cross-Origin-Resource-Policy is the answer to COEP's demand, set by the resource rather than the embedder. Three values: same-origin, same-site, cross-origin. A public asset that wants to be embeddable anywhere sends cross-origin; anything else narrows it.
It is also the oldest and best-supported of the three, which makes sense — it is the piece a CDN or an image host has to ship before anyone else's isolation can work.
Warning
A malformed or unparseable CORP header fails open. The Fetch algorithm sets the policy to null when it cannot parse the value, and null under an unsafe-none embedder policy means allowed. The spec notes the consequence directly: Cross-Origin-Resource-Policy: same-site, same-origin "will never match anything" and ends up allowed. Two CORP headers have the same effect. A typo here does not fail safe.
The conjunction
Now the part that explains the adoption numbers.
Cross-origin isolation is not something either header grants. It is a value in the spec's internal enumeration — same-origin-plus-COEP — and the HTML Standard says exactly how you get it:
"same-origin-plus-COEP" cannot be directly set via the
Cross-Origin-Opener-Policyheader, but results from a combination of setting bothCross-Origin-Opener-Policy: same-originand aCross-Origin-Embedder-Policyheader whose value is compatible with cross-origin isolation together.
Two headers, set independently, producing a state that neither one can express on its own. COOP orders its values from permissive to strict (unsafe-none, same-origin-allow-popups, same-origin); so does COEP (unsafe-none, credentialless, require-corp). Isolation is a threshold on the pair: you must be at or above a specific point on both axes.
There is no partial credit. A site with same-origin-allow-popups and require-corp is exactly as isolated as a site with neither: not at all.
That is not a pedantic observation — it reframes the deployment problem. Most security headers reward incremental adoption: a slightly stricter CSP is slightly better. The isolation pair does not. Every point short of the corner is the same value, which means partial migration produces no benefit to point at, no metric that improves, nothing to justify the next quarter's work with. It is an all-or-nothing gate on a multi-team migration, which is a bad combination.
The report-only mode mirrors the conjunction
There is a pleasing consequence, and a practical trap inside it. Both headers have report-only variants, and the isolation state they simulate is reached the same way — by combining them. The COOP reporting explainer, written by the spec's author, is explicit: setting both Cross-Origin-Opener-Policy-Report-Only: same-origin and Cross-Origin-Embedder-Policy-Report-Only: require-corp "will lead the document to have a report only COOP value of same-origin-plus-COEP."
So the dry run is a conjunction too. Deploy only one report-only header and you are not rehearsing the state you intend to reach — you are measuring a different one. The design is deliberate: it means "developers do not need to choose which one should move out of report-only mode first."
Important
Report-only telemetry here is, in practice, a Chrome-only instrument: the report-to parameter on both COOP and COEP is unsupported in Firefox and Safari. You can still deploy the report-only headers everywhere; you will mostly hear back from one engine. Plan the rollout knowing your evidence has a browser-shaped bias.
What you get, and what breaks
The cost of not having this mechanism was already paid, by everyone, and it is worth naming because it is unusual: the bill did not land on the sites that skipped a header. It landed on the platform.
In January 2018 Spectre showed that a sufficiently precise clock lets a page infer memory it was never handed, by timing the cache. SharedArrayBuffer plus Atomics is a sufficiently precise clock. Browsers disabled SharedArrayBuffer within days — not for pages that had misconfigured something, but for every page on the web — and coarsened performance.now() alongside it. The feature stayed gone for roughly two years.
It came back in 2020 with a condition attached, and the condition is this article's subject. A page may have the sharp tools again once it can demonstrate that nothing it did not vet shares its address space, which is exactly what COOP, COEP and CORP demonstrate together. The headers are not a tax on the feature; they are the evidence the feature now requires.
That is the honest answer to "why should I deploy three headers for a capability I do not use." Today the price of skipping them is that SharedArrayBuffer, the finer clock, and memory measurement are unavailable to you. The mechanism is how a page proves it deserves them.
What isolation unlocks is a short list, and shorter than commonly claimed: SharedArrayBuffer, a higher-resolution performance.now(), and performance.measureUserAgentSpecificMemory().
The gate itself sits somewhere unexpected. It is not in the SharedArrayBuffer constructor but in structured serialization — the spec throws a DataCloneError when serializing a SharedArrayBuffer if the cross-origin isolated capability is false. The reason given is a small, elegant invariant: the check "is only needed when serializing (and not when deserializing) as the cross-origin isolated capability cannot change over time and a SharedArrayBuffer cannot leave an agent cluster."
Note
You will find sources adding the JS Self-Profiling API to that list. As far as its specification is concerned, that is wrong: the profiler gates on Document-Policy: js-profiling, not on cross-origin isolation, and MDN's own crossOriginIsolated page does not list it. If a capability matters to you, check its spec rather than a summary — including this one.
What breaks is a longer list, and its most useful property is that it breaks unevenly. web.dev's guidance notes that missing-CORP images fail visibly — "the request will be blocked and the page will indicate a missing image" — while for scripts and styles, COEP issues "might go unnoticed" without opening the network panel. A loud failure for the resource type you would notice anyway; a quiet one for the types that change behavior.
Warning
Plan for the silent half. An image that vanishes gets reported by the first person who looks at the page; a stylesheet or a script that was refused produces a page that renders and then behaves subtly wrong. The broken behavior is the argument for the report-only pass being a real phase with someone reading the output, rather than a box ticked on the way to enforcement.
Why almost nobody has this
The Web Almanac's 2025 security chapter puts CORP above 2.25% of sites, COOP at about 2.0%, and COEP lowest at roughly 0.75%. Those are the headline numbers, and the distribution underneath them is more telling: of the sites that send COEP at all, about 83% send unsafe-none — that is, the majority of COEP deployments are explicitly declining isolation.
Combine the two facts and actual cross-origin isolation is somewhere in the neighbourhood of one site in a thousand. (Treat that as a sketch rather than a measurement — the percentages come from different denominators.)
The reasons are structural rather than cultural, and by now they should look familiar:
- The gate is all-or-nothing, so partial progress shows no benefit.
- The cost lands on third parties, who must ship CORP before your isolation can work — and they have no incentive from your deadline.
- It breaks popups, which is where authentication and payment live.
- Half the failures are silent, so the migration's true cost is unknown until late.
COEP: credentialless relaxes the demand: cross-origin no-cors requests are sent without credentials instead of being refused, so a third party that never set CORP still loads. It is the pragmatic path — on Chrome and Firefox desktop. Safari does not implement it, and neither does Firefox on Android.
Two things you will read that are not true
"credentialless means you no longer need CORP." Not for frames. Chrome's own announcement is explicit that loading cross-origin iframes under credentialless "still requires the same conditions as require-corp" — the framed document needs both a COEP header and Cross-Origin-Resource-Policy: cross-origin. Subresources are relaxed; iframes are not.
"credentialless is the pragmatic cross-browser answer." It is Chrome-and-Firefox-desktop. If your isolation has to work in Safari, you are back to require-corp and to persuading every third party you embed to send CORP. The team behind StackBlitz — whose product depends on SharedArrayBuffer — published a call to action about precisely this gap, which is a fair indication of how much it constrains real products.
What comes next
There is a plausible exit from the conjunction, and it is worth knowing about even though it is not yet something to build on. Document-Isolation-Policy is a proposed header that, in the spec's words, "enables crossOriginIsolation for the document, without relying on COOP and COEP." It is backed by process isolation directly, which is what lets it drop the requirements that make the current design painful: per Chrome's announcement, it "applies per frame and makes no requirements of subframes," and documents using it "can open cross-origin popups and communicate with them."
That would dissolve most of this article's difficulty — no subresource cooperation, no broken OAuth.
Important
On 2026-08-12, Document-Isolation-Policy was a one-engine feature. It shipped in Chrome 137 for desktop. Mozilla's and WebKit's standards-position issues are both open with no position stated, and WebKit's carries labels flagging portability concerns. A one-engine solution to a problem whose cost is cross-browser support is not yet a solution; watch it, don't build on it.
The shape of the whole thing
The thing worth carrying away is not the header syntax. It is the shift underneath it.
Access control asks may this code read that data? and answers with a rule. That worked while the rule was the only thing standing between two origins in one address space. Spectre demonstrated that the rule could be bypassed without being broken — no browser bug, no privilege escalation, just physics that the security model had assumed away.
What replaced it is a residency question: may that data be here at all? It is a weaker-sounding question that turns out to be much stronger, because it does not depend on any boundary holding inside the process. And because the browser cannot infer the answer, the three headers exist to supply it — one for who may share your context, one to demand that everything opt in, one to do the opting.
That the resulting property is a conjunction, and that fewer than one site in a hundred has assembled it, is the honest measure of what the shift cost.
Lessons
- The same-origin policy is access control, and Spectre defeated access control without defeating the rule. The Site Isolation authors' memory disclosure attacker needs "no bugs in web browser code."
- So the question changed from "may this document read that data?" to "may that data be in this process?" — residency rather than permission.
- COOP decides who shares your browsing context group; the cost is popups, which is where OAuth and payments live.
- COEP does not add a check, it changes a default — under
require-corpa resource with no CORP header is treated assame-origin, and therefore refused. - CORP is the resource's answer, set by whoever serves it, which is why a site's isolation depends on third parties shipping a header for reasons of their own.
crossOriginIsolatedis a conjunction no single header can express. The spec'ssame-origin-plus-COEP"cannot be directly set" and results only from combining both. There is no partial credit: one notch short on either axis is worth as much as no headers at all.- The report-only pair mirrors the conjunction, so a dry run needs both headers — and its telemetry is effectively Chrome-only.
- Failures are uneven: a missing image is visible, a refused script is not.
- Adoption is ~2% COOP, ~0.75% COEP, and 83% of COEP senders use
unsafe-none. The gate's all-or-nothing shape is a sufficient explanation. credentiallessis not the universal answer — Chrome and Firefox desktop only, and cross-origin iframes still need CORP regardless.
Practice
References
- Kocher, Horn, Fogh, Genkin, Gruss, Haas, Hamburg, Lipp, Mangard, Prescher, Schwarz, Yarom. “Spectre Attacks: Exploiting Speculative Execution.” IEEE Symposium on Security and Privacy, 2019. — the attack that made co-residency the vulnerability, including the JavaScript demonstration
- Reis, Moshchuk, Oskov. “Site Isolation: Process Separation for Web Sites within the Browser.” USENIX Security, 2019. — the browser's architectural response, its threat model, and the measured cost
- WHATWG. “Cross-origin opener policies.” HTML Standard. — the five internal values, and the statement that same-origin-plus-COEP cannot be set directly
- WHATWG. “Cross-Origin-Resource-Policy header.” Fetch Standard. — the internal check where COEP substitutes the default policy, and the fail-open parsing note
- MDN. “Window.crossOriginIsolated.” MDN. — what the property requires and what it unlocks
- MDN. “Cross-Origin-Embedder-Policy.” MDN. — require-corp and credentialless semantics
- Google. “Why you need cross-origin isolation.” web.dev. — the Spectre rationale, and the uneven-failure observation
- Camille Lamy. “COOP reporting explainer.” GitHub. — why the report-only pair reproduces the conjunction
- WICG. “Document-Isolation-Policy.” WICG Draft Community Group Report, 2025. — the proposed exit from the COOP+COEP requirement
- Google. “Document Isolation Policy.” Chrome for Developers, 2025. — what it drops, and the Chrome-137-desktop shipping status
- HTTP Archive. “Web Almanac 2025: Security.” HTTP Archive, 2025. — adoption shares and the value distributions underneath them
- StackBlitz. “Bringing WebContainers to all Browsers.” StackBlitz Blog. — a product whose viability depends on credentialless support, arguing for it publicly
How to cite
Mangalapilly, Y. J. (2026, August). Nobody Shares Your Address Space. Saṃhitā Notes. https://yesudeep.com/blog/nobody-shares-your-address-space/ @online{mangalapilly2026nobody,
author = {Yesudeep Jose Mangalapilly},
title = {Nobody Shares Your Address Space},
journal = {Sa\d{m}hit\=a Notes},
year = {2026},
month = {August},
url = {https://yesudeep.com/blog/nobody-shares-your-address-space/},
urldate = {2026-08-12},
} Yesudeep Jose Mangalapilly. “Nobody Shares Your Address Space.” Saṃhitā Notes, 2026. https://yesudeep.com/blog/nobody-shares-your-address-space/. TY - ELEC
AU - Mangalapilly, Yesudeep Jose
TI - Nobody Shares Your Address Space
T2 - Saṃhitā Notes
PY - 2026
UR - https://yesudeep.com/blog/nobody-shares-your-address-space/
Y2 - 2026-08-12
ER - Webmentions
Annotations
Thank you — your note is held for review and will appear once approved.
Thank you — your note is published.
Please sign in below to leave a note.
