How Chromium Restricts Third-Party Storage in Frames
This article explains how the Chromium web browser restricts and
isolates third-party storage APIs, such as localStorage and IndexedDB,
within partitioned frames. By implementing storage partitioning,
Chromium prevents cross-site tracking by binding third-party storage
data to the specific top-level website where the frame is embedded.
Additionally, this overview covers how Chromium's internal
StorageKey mechanism functions and how user-level privacy
settings can completely deny access to these storage APIs in third-party
contexts.
The Shift from Origin-Keyed to Partitioned Storage
Historically, web browsers keyed storage APIs like
localStorage and IndexedDB solely by the
origin of the frame accessing them. If an iframe from
example-tracker.com was embedded on both
site-a.com and site-b.com, it could access the
exact same storage bucket on both websites. This allowed third parties
to track users across the web by storing unique identifiers in
localStorage or IndexedDB.
Chromium restricts this behavior through a mechanism called Storage Partitioning. Instead of granting a third-party iframe access to a global storage bucket based only on its own origin, Chromium forces the iframe to use an isolated storage bucket that is specific to the top-level site the user is currently visiting.
How Chromium's StorageKey Works
To enforce partitioning at the browser architecture level, Chromium
replaces simple origin checks with a composite key known as a
StorageKey. When a frame requests access to
localStorage, IndexedDB,
CacheStorage, or the Origin Private File System (OPFS),
Chromium generates a StorageKey made of three main
components:
- The Frame Origin: The exact origin (scheme, host, and port) of the embedded frame requesting the storage.
- The Top-Level Site: The "schemeful site" (scheme and registrable domain, or eTLD+1) of the main page the user is visiting in the address bar.
- The Ancestor Chain Bit: A boolean value that indicates whether there are any cross-site frames located between the requesting frame and the top-level site.
Because of this key structure, an iframe from widget.com
embedded on news.com is assigned a StorageKey
combining both domains. If the same widget.com iframe is
embedded on weather.com, it receives a completely different
StorageKey. The data written to IndexedDB or
localStorage on one site is entirely invisible and
inaccessible when the iframe loads on the other site.
Handling Nested Frames (The Ancestor Chain)
Chromium also restricts storage access in complex nested scenarios,often referred to as "A-B-A" embeds.
If site-a.com is the top-level page, and it embeds a
cross-site iframe from site-b.com, which in turn embeds an
iframe from site-a.com, the inner site-a.com
frame is not granted access to the top-level site-a.com
storage. The Ancestor Chain Bit detects site-b.com in the
hierarchy and marks the inner frame as cross-site. Consequently, the
inner site-a.com frame is restricted to a separate,
partitioned storage bucket to prevent site-b.com from
exploiting it to access first-party data.
Complete Blocking via User Settings
Beyond partitioning, Chromium ties the availability of DOM storage APIs directly to the browser's cookie settings. For Chromium, "cookies and site data" are governed by the same permission model.
If a user configures their Chromium browser to block third-party
cookies entirely, Chromium strips third-party iframes of their ability
to even use partitioned storage. When an embedded cross-site frame
attempts to access window.localStorage or call
indexedDB.open() under these strict settings, the browser
intercepts the call and immediately throws a SecurityError
(a DOMException).
Ephemeral Partitioning in Opaque Origins
For frames that utilize the sandbox attribute (without
the allow-same-origin token) or anonymous iframes (fenced
frames/credentialless iframes), Chromium restricts storage further by
adding a cryptographic nonce (a random, single-use number) to the
StorageKey.
In these instances, if the sandboxed frame is permitted to access storage APIs at all, the storage is completely ephemeral. It is isolated not only from other sites, but also from other frames on the exact same page, and the data is permanently wiped by the browser the moment the user closes the tab or navigates away.