v150 · Security · demo

Origin Isolation Demo

Run the tests below to see how Chrome 150 changes the origin of workers created from data: URLs. In Chrome 149 and older, self.origin inside such a worker returned your page's origin — giving the worker same-origin access. In Chrome 150 it returns "null", blocking same-origin APIs.

Detecting Chrome version…
Chrome 149 and older — inherited origin

A data: URL worker inherits the creator page's origin. self.origin returns the page's origin string. Origin-scoped APIs like BroadcastChannel delivery and IndexedDB access share the page's namespace.

self.origin
BC delivery
localStorage exposure
IndexedDB open
Chrome 150+ — opaque origin

A data: URL worker gets a unique opaque origin. self.origin returns "null". BroadcastChannel may still construct, but the page should not receive its messages; direct postMessage remains the safe communication path.

self.origin
BC delivery
localStorage exposure
IndexedDB open

What the test does

The demo creates a Dedicated Worker from a data: URL containing a small script. The page opens a BroadcastChannel with a random name, the worker constructs the same channel and posts a probe, and the page waits briefly to see whether that broadcast arrives. In Chrome 150+ construction can still succeed, but delivery should not cross from the opaque-origin worker into the page's channel namespace. The worker also reports self.origin, confirms localStorage is not exposed to workers, and attempts an IndexedDB open.

Test worker — created from a data: URL
// Worker source — stringified and turned into a data: URL const workerSrc = ` // What origin does this worker have? const origin = self.origin; // "null" in Chrome 150+ // BroadcastChannel can construct; delivery is the security probe. const bc = new BroadcastChannel(channelName); bc.postMessage({ origin }); bc.close(); // Try localStorage (not available in workers) let lsStatus = typeof localStorage !== 'undefined' ? 'accessible' : 'not in workers'; // Try IndexedDB (blocked for opaque origins) const req = indexedDB.open('test'); req.onsuccess = () => postMessage({ origin, idbStatus: 'open succeeded' }); req.onerror = () => postMessage({ origin, idbStatus: req.error.name }); `; const url = 'data:text/javascript,' + encodeURIComponent(workerSrc); const worker = new Worker(url); // ← Chrome 150 gives opaque origin worker.onmessage = (e) => console.log(e.data);

see also

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗