Browsers keep track of the pages that a user has visited, and they use this information to style anchor elements on a page differently if a user has visited that link before. Most browsers give visited links a different color by default; some web developers rely on the :visited CSS selector to style visited links according to their own preferences.
It is well-known that styling visited links differently from unvisited links opens the door to side-channel attacks that leak the user’s browsing history. One notable attack used window.getComputedStyle and the methods that return a NodeList of HTMLCollection of anchor elements (e.g. document.querySelectorAll, document.getElementsByTagName, etc.) to inspect the styles of each link that was rendered on the page. Once attackers had the style of each link, it was possible to determine whether each link had been visited, leaking sensitive information that should have only been known to the user.
In 2010, browsers implemented a mitigation for this attack: (1) when sites queried link styling, the browser always returned the “unvisited” style, and (2) developers were now limited in what styles could be applied to links. However, these mitigations were complicated for both browsers to implement and web developers to adjust to, and there are proponents of removing these mitigations altogether.
Since 2010, the number of side-channel attacks to leak the user’s browsing history from :visited links styling has grown, including user interaction attacks, timing attacks, pixel color attacks, and process-level attacks. While these attack vectors are slowed down by the 2010 mitigations, they are not eliminated; browsers are still actively leaking user browsing history today.
Our goal is to improve user privacy by eliminating :visited links history leaks by ensuring the information available via side-channel attacks on :visited links is no longer valuable or net-new to attackers. To meet our stated goals, we propose partitioning :visited links history. For the purpose of this proposal, partitioning is defined as storing visited links history via partition key, rather than just by the link URL. When a renderer queries the stored visited links, only queries that match all the elements of the partition key may be colored as visited on the page. On the user’s end, this will mean that the browser styles links as :visited if and only if they have been visited from this site and frame before.
Introduction
Browsers keep track of the pages that a user has visited, and they use this information to style anchor elements on a page differently if a user has visited that link before. Most browsers give visited links a different color by default; some web developers rely on the :visited CSS selector to style visited links according to their own preferences.
It is well-known that styling visited links differently from unvisited links opens the door to side-channel attacks that leak the user’s browsing history. One notable attack used window.getComputedStyle and the methods that return a NodeList of HTMLCollection of anchor elements (e.g. document.querySelectorAll, document.getElementsByTagName, etc.) to inspect the styles of each link that was rendered on the page. Once attackers had the style of each link, it was possible to determine whether each link had been visited, leaking sensitive information that should have only been known to the user.
In 2010, browsers implemented a mitigation for this attack: (1) when sites queried link styling, the browser always returned the “unvisited” style, and (2) developers were now limited in what styles could be applied to links. However, these mitigations were complicated for both browsers to implement and web developers to adjust to, and there are proponents of removing these mitigations altogether.
Since 2010, the number of side-channel attacks to leak the user’s browsing history from :visited links styling has grown, including user interaction attacks, timing attacks, pixel color attacks, and process-level attacks. While these attack vectors are slowed down by the 2010 mitigations, they are not eliminated; browsers are still actively leaking user browsing history today.
Our goal is to improve user privacy by eliminating :visited links history leaks by ensuring the information available via side-channel attacks on :visited links is no longer valuable or net-new to attackers. To meet our stated goals, we propose partitioning :visited links history. For the purpose of this proposal, partitioning is defined as storing visited links history via partition key, rather than just by the link URL. When a renderer queries the stored visited links, only queries that match all the elements of the partition key may be colored as visited on the page. On the user’s end, this will mean that the browser styles links as :visited if and only if they have been visited from this site and frame before.
Read the complete Explainer.
Feedback
I welcome feedback in this thread, but encourage you to file bugs against the explainer.