Leaks through the edges
Why it matters Not everything a browser remembers is labelled "storage". Speed features such as caches and reused connections also remember things, and anything that remembers can carry an ID or reveal where you have been. These edges are where careful engines differ from careless ones.
Imagine a librarian who keeps the most popular books on a front shelf to save time. That is helpful. But if one visitor asks for a rare book and the next visitor can tell, by how fast it arrives, that someone asked for it recently, the shelf has become a message board. Caches are front shelves.
Side channel: information that leaks not from what a system says but from how it behaves, such as how long something takes or whether a connection was reused.
The HTTP cache
HTTP cache: the browser's saved copies of files (scripts, images, pages) so they load faster next time.
An unpartitioned cache leaks in two ways. First, timing: a page on prize.example loads an image from shopb.example; if it arrives instantly, it was cached, so you probably visited ShopB. Second, tagging: a server sends a file with a unique validator tag (an ETag), and your browser repeats that tag when it checks whether the file has changed, which works like a cookie.
The fix is to add the top-level site (and, in some engines, the frame's site) to the cache key, next to the URL. The same image loaded under two different sites is then stored twice. The cost is real: a popular library on a shared server no longer loads instantly on the second site that uses it.
Connection pools
Connection pool: open, encrypted connections to servers that the browser keeps for a while and reuses, so the next request skips the setup handshake.
If adco.example is embedded on ShopA and then on ShopB, and both requests travel over one reused connection, AdCo's server can link them without any cookie: same connection, same browser. Partitioned engines keep separate pools per top-level site. Many smaller caches carry similar risks, such as the DNS cache (remembered name lookups) and data the browser keeps to resume encrypted sessions quickly.
The HTTP cache and connection pools are partitioned in all three major engines: Safari since 2013, Chrome since version 86 and Firefox since version 85, whose network partitioning also covered many smaller caches (checked October 2026).
Visited links
:visited: the style a page can give links you have already been to, such as purple instead of blue.
For years, a page could list hundreds of links and check which ones were purple, learning your history. This is called history sniffing. Browsers responded by limiting what a visited link may change (essentially colours) and by making scripts that ask for a link's style always get the unvisited answer. Researchers still found timing and drawing tricks around those limits.
Chrome 136 (2025) went further and partitioned visited-link history: a link shows as visited only if you clicked it under the same top-level site and frame origin, keyed on the link URL, the top-level site and the frame origin. Firefox and Safari restrict the styles a visited link may use, but do not partition the history itself (checked October 2026).
| Edge | What leaks | Fix |
|---|---|---|
| HTTP cache | past visits by timing; IDs in validator tags | top-level site in the cache key |
| Connection pool | one connection links two sites' requests | separate pools per top-level site |
| Visited links | your history, through link styles | style limits; partitioned history (Chrome 136) |
Try it On a page where a link shows in the visited colour, right-click that link and choose Inspect. DevTools opens with the link selected. Go to the Console tab and type getComputedStyle($0).color ($0 means "the element I just inspected"). The answer is the unvisited colour even though the link looks purple on screen: the browser is lying to scripts on purpose. Then open DevTools' Network panel, reload twice, and notice files marked as served from the cache.
A common misconception
"If nothing is written to disk, nothing can leak." A reused connection or a fast answer leaks without any stored value. The rule engine builders follow is: anything that changes behaviour based on the past is state, and state needs a partition key.
Recap
- Caches and connection pools remember, so they can reveal history or carry IDs.
- All three engines partition the HTTP cache and connection pools (Safari 2013, Chrome 86, Firefox 85).
- Chrome 136 partitions visited-link history; Firefox and Safari limit visited-link styles instead.
- Partitioning costs some speed, because shared files are fetched again per site.
This lesson is locked
Lessons open one at a time. Finish the previous lesson to unlock this one.