Intent to Ship: Partitioning :visited links history

607 views
Skip to first unread message

Kyra Seevers

unread,
Feb 14, 2025, 1:35:43 PMFeb 14
to blink-dev

Contact emails

kyras...@chromium.org, mike...@chromium.org, a...@google.com


Explainer

https://github.com/explainers-by-googlers/Partitioning-visited-links-history


Specification

https://drafts.csswg.org/selectors-4/#visited-privacy


Summary

To eliminate user browsing history leaks, anchor elements are styled as :visited only if they have been clicked from this top-level site and frame origin before. On the browser-side, this means that the VisitedLinks hashtable is now partitioned via "triple-keying", or by storing the following for each visited link: <link URL, top-level site, frame origin>. By only styling links that have been clicked on this site and frame before, the many side-channel attacks that have been developed to obtain :visited links styling information are now obsolete, as they no longer provide sites with new information about users. 


There is an exception for "self-links", where links to a site's own pages can be styled as :visited even if they have not been clicked on in this exact top-level site and frame origin before. This exemption is only enabled in top-level frames or subframes which are same-origin with the top-level frame. The privacy benefits above are still achieved because sites may already know which of its subpages a user has visited, so no new information is exposed. This was a community-requested exception which improves user experience as well.


Blink component

Blink>History>VisitedLinks


Search tags

visited links, :visited selector, partitioning history


TAG review

https://github.com/w3ctag/design-reviews/issues/896


TAG review status

Satisfied with concerns


Risks



Interoperability and Compatibility

There has been lots of word-of-mouth and official interest from the Web Platform in adopting this feature cross-browser.


Gecko: Positive (https://github.com/mozilla/standards-positions/issues/1040)


WebKit: No signal (https://github.com/WebKit/standards-positions/issues/363)


Web developers: No official signals, see below for more details


Other signals: Positive or neutral initial signals from security and privacy researchers at the XS-Leaks summit. There are no security concerns about this design and lots of interest in finally resolving this exploit. Feedback from UX that CSS extensibility is in-demand from developers right now, and this work would pave the way for less restricted CSS on anchor elements. In addition, support from various developers who believe that taking care of this long-standing privacy leak will allow their own security and privacy solutions to advance once history sniffing is no longer an issue.


Ergonomics

This design is asynchronous and not used in tandem with other APIs.


Activation

Since this is a Finch roll-out, there are no additional activation risks.


Security

For this design we worked with the Chrome Security Architecture team to ensure reasonable precautions were taken against leaks via renderer compromises.


WebView application risks

There is no risk for WebView based-applications because WebView has its own History system and stores :visited links using different code from the other platforms. For this reason, we are not shipping triple-key partitioning to WebView.



Debuggability

No DevTools support is required.



Will this feature be supported on all six Blink platforms (Windows, Mac, Linux, ChromeOS, Android, and Android WebView)?

No

This feature is not currently supported on iOS or Android Webview. For iOS, this feature requires WebKit to alter its CSS parsing to support triple-key partitioning. Android Webview relies on an entirely different system to populate history, so it will require a separate design.



Is this feature fully tested by web-platform-tests?

No

This feature is not tested by automated Web Platform Tests because the :visited selector, in its current state, cannot be queried via JavaScript (https://developer.mozilla.org/en-US/docs/Web/CSS/Privacy_and_the_:visited_selector). As a result, we can only test :visited-ness via a manual test which relies on users visually confirming the correct links are :visited, or unit and integration tests internal to Chrome.


DevTrial instructions

https://github.com/explainers-by-googlers/Partitioning-visited-links-history?tab=readme-ov-file#how-to-experiment


Flag name on about://flags

#partition-visited-link-database-with-self-links


Finch feature name

PartitionVisitedLinkDatabaseWithSelfLinks


Requires code in //chrome?

True - code is added to 2 areas of //chrome code:

  1. chrome/browser/history/history_tab_helper.h/.cc to add explicit parameters for top-level site and is_ephemeral to HistoryAddPageArgs and populate them; we later access this information in non-chrome code to add navigations to the history database

  2. chrome/browser/chrome_content_browser_client.cc to add a navigation throttle which intercepts the origins of incoming navigations (doesn’t actually throttle) to calculate its per-origin salt. This was added as part of the mitigations to prevent the entire table being leaked in the event of a renderer compromise.


Tracking bug

https://bugs.chromium.org/p/chromium/issues/detail?id=1448609


Launch bug

https://launch.corp.google.com/launch/4330864


Availability expectation

Other browsers have expressed interest in implementing :visited links partitioning at TPAC 2023 and 2024. I expect that the feature is available across the Web Platform in the next couple of years.


Non-OSS dependencies

Does the feature depend on any code or APIs outside the Chromium open source repository and its open-source dependencies to function?

No


Estimated milestones

Enabled by Default on Desktop and Android*

135

Stable 100% via Finch on Desktop and Android*

133

Multi-Arm Finch Experiment Began

128

Multi-Arm Finch Experiment Ended

133

Database Finch Experiment Began

118

Database Finch Experiment Ended

121

DevTrial on Desktop and Android Began

132


* We intend to launch to Stable 100% via Finch configuration, which will have a min milestone of M133. The corresponding ENABLED_BY_DEFAULT chromium CL will likely land in M135.


Anticipated spec changes

The current CSS Selectors spec language is broad enough to support partitioning :visited link history. However, we have added specification that UAs MUST take some action to protect user browsing history [1], with a note which describes our triple-key solution [2]:

[1] https://drafts.csswg.org/selectors-4/#link 

[2] https://drafts.csswg.org/selectors-4/#visited-privacy


Link to entry on the Chrome Platform Status

https://chromestatus.com/feature/5101991698628608?gate=5127548398206976


Links to previous Intent discussions

Intent to Prototype: https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CA%2BmmbXbbLWwmRYH5SWx0%2BMWkfB2UY2miOAq4r0MZc34i_sWqBw%40mail.gmail.com

Intent to Experiment (Phase 1): https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CA%2BmmbXYy4CSMuPLY0HJuTbZt0qPz5ZUsGUToFJuCE%2BTfC86umA%40mail.gmail.com

Intent to Experiment (Phase 2): https://groups.google.com/a/chromium.org/g/blink-dev/c/U5AX0OXaxM8/m/tIGr4bJJBgAJ?utm_medium=email&utm_source=footer

Ready for Trial: https://groups.google.com/a/chromium.org/g/blink-dev/c/lg73meqgggo/m/dgqIFrveDgAJ?utm_medium=email&utm_source=footer



This intent message was generated by Chrome Platform Status.


Domenic Denicola

unread,
Feb 16, 2025, 8:43:55 PMFeb 16
to Kyra Seevers, blink-dev
Very exciting to see progress on this longstanding problem!

As you note below, this isn't a real specification of the behavior you're proposing to ship. Instead, it contains that behavior in a non-normative appendix.

It's therefore unclear to what extent the behavior here represents cross-browser consensus, and what types of interop and compat risks this is leaving us up to.

Can you say more about what's missing from getting a cross-browser agreed-upon algorithm specified by the CSSWG? Are there other candidate algorithms that other browsers are championing, which we might be in conflict with?
Couldn't this be tested with reftests

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CA%2BmmbXY%3D2PpZ9cQ5EQBLDwi2F6O7gocPDm7cZEw-6C2huodEmg%40mail.gmail.com.

Tab Atkins Jr.

unread,
Feb 18, 2025, 12:36:45 PMFeb 18
to Domenic Denicola, Kyra Seevers, blink-dev
On Sun, Feb 16, 2025 at 5:43 PM Domenic Denicola <dom...@chromium.org> wrote:
Very exciting to see progress on this longstanding problem!

On Sat, Feb 15, 2025 at 3:35 AM Kyra Seevers <kyras...@chromium.org> wrote:

As you note below, this isn't a real specification of the behavior you're proposing to ship. Instead, it contains that behavior in a non-normative appendix.

It's therefore unclear to what extent the behavior here represents cross-browser consensus, and what types of interop and compat risks this is leaving us up to.

Can you say more about what's missing from getting a cross-browser agreed-upon algorithm specified by the CSSWG? Are there other candidate algorithms that other browsers are championing, which we might be in conflict with?

This has been discussed with the working group several times, starting from the 2023 TPAC meeting, so the WG is well aware of the proposal. More recently, the WG resolved to upgrade the language in Selectors to *require* being privacy-preserving, and add our algorithm as an appendix for now.

As the behavior is still untested in stable, the WG didn't want to adopt it precisely yet. After we've had it on for a while and confirmed that it still suits users' needs, we plan to bring it back to the WG for more official adoption. Private discussion with other vendors suggests that they expect to adopt it (or something very close to it) anyway as long as we stick with it, since we're going to at some point remove the :visited styling restrictions (once we're confident about this approach), and that's likely to become a cross-browser compat issue afterwards.

So, the only blocker to making this official is that the WG (and us, tbh) want to see it working in practice first.
 
There's no counter-proposal besides just continuing with the current semi-documented styling restrictions.

Is this feature fully tested by web-platform-tests?

No

This feature is not tested by automated Web Platform Tests because the :visited selector, in its current state, cannot be queried via JavaScript (https://developer.mozilla.org/en-US/docs/Web/CSS/Privacy_and_the_:visited_selector). As a result, we can only test :visited-ness via a manual test which relies on users visually confirming the correct links are :visited, or unit and integration tests internal to Chrome.


Couldn't this be tested with reftests

Eh, probably, but possibly with some flakiness. Emilio voiced concern about assuming a synchronous styling of :visited links (in <https://github.com/w3c/csswg-drafts/issues/11151#issuecomment-2607888849>). But if we're okay with a delay that will *probably* work, reftests are likely possible.

I expect the main issue is going to be having cross-domain tests. We probably already have some framework for serving some files from a different domain in WPT, yeah? I've never had to deal with that issue before.

~TJ

Christian Biesinger

unread,
Feb 18, 2025, 1:54:06 PMFeb 18
to Tab Atkins Jr., Domenic Denicola, Kyra Seevers, blink-dev

Yoav Weiss (@Shopify)

unread,
Feb 19, 2025, 6:44:15 AMFeb 19
to blink-dev, jacka...@gmail.com, Kyra Seevers, blink-dev, Domenic Denicola
On Tuesday, February 18, 2025 at 6:36:45 PM UTC+1 jacka...@gmail.com wrote:
On Sun, Feb 16, 2025 at 5:43 PM Domenic Denicola <dom...@chromium.org> wrote:
Very exciting to see progress on this longstanding problem!

+1000000
 

On Sat, Feb 15, 2025 at 3:35 AM Kyra Seevers <kyras...@chromium.org> wrote:

As you note below, this isn't a real specification of the behavior you're proposing to ship. Instead, it contains that behavior in a non-normative appendix.

It's therefore unclear to what extent the behavior here represents cross-browser consensus, and what types of interop and compat risks this is leaving us up to.

Can you say more about what's missing from getting a cross-browser agreed-upon algorithm specified by the CSSWG? Are there other candidate algorithms that other browsers are championing, which we might be in conflict with?

This has been discussed with the working group several times, starting from the 2023 TPAC meeting, so the WG is well aware of the proposal. More recently, the WG resolved to upgrade the language in Selectors to *require* being privacy-preserving, and add our algorithm as an appendix for now.

As the behavior is still untested in stable, the WG didn't want to adopt it precisely yet.

Could the relevant spec language live in a PR? Having such language would make it easier to evaluate the gap between the current CSS spec and the ability to specify this behavior in an interoperable way.

Alex Russell

unread,
Feb 19, 2025, 11:43:18 AMFeb 19
to blink-dev, Yoav Weiss, jacka...@gmail.com, Kyra Seevers, blink-dev, Domenic Denicola
I'm also super excited about this. Has been a long time coming. Thank you for making it happen, Kyra!

On compat, can we allay the concerns here with a fractional rollout (e.g., ~10% for a couple of releases) and a checkin at some point(s) before we go to 100%?

Best,

Alex

Tab Atkins Jr.

unread,
Feb 19, 2025, 3:34:46 PMFeb 19
to Yoav Weiss (@Shopify), blink-dev, Kyra Seevers, Domenic Denicola
On Wed, Feb 19, 2025 at 3:44 AM Yoav Weiss (@Shopify)
<yoav...@chromium.org> wrote:
> Could the relevant spec language live in a PR? Having such language would make it easier to evaluate the gap between the current CSS spec and the ability to specify this behavior in an interoperable way.

The current appendix should describe the behavior in sufficient detail
for that purpose: it details exactly how to construct the caching key
and what keys to add, using the specific HTML terms (origin, site)
that we're relying on. Official spec text would just be slightly more
precise with its terms, but not, afaict, in a way that would affect
implementability.

This is already more detail than what is specified for our *existing*
:visisted behavior, fwiw, which just exists in an MDN page and still
leaves many precise details (such as exactly what selectors are
allowed) to the imagination.

~TJ

Kyra Seevers

unread,
Feb 19, 2025, 3:55:13 PMFeb 19
to Tab Atkins Jr., Yoav Weiss (@Shopify), blink-dev, Domenic Denicola
Hi all - thanks for your review!

> Couldn't this be tested with reftests
I'm happy to work on a reftest to add the benefit of test automation, but in the meantime, I have landed a manual test to verify the same behavior.

> On compat, can we allay the concerns here with a fractional rollout (e.g., ~10% for a couple of releases) and a check-in at some point(s) before we go to 100%
The plan is to do a cautious-style Finch rollout, rolling out by increasing percentages of stable (like Stable 10%), before completely rolling out to Stable 100%.

Let me know if you have any more questions!
Thanks,
Kyra

Yoav Weiss (@Shopify)

unread,
Feb 20, 2025, 12:45:09 AMFeb 20
to blink-dev, Kyra Seevers, Yoav Weiss, blink-dev, Domenic Denicola, jacka...@gmail.com
One point worth clarifying - this intent doesn't relax the current restrictions on visited styling, right?
Are there plans to follow up with that? That seems like something designers would be happy with..

On Wednesday, February 19, 2025 at 9:55:13 PM UTC+1 Kyra Seevers wrote:
Hi all - thanks for your review!

> Couldn't this be tested with reftests
I'm happy to work on a reftest to add the benefit of test automation, but in the meantime, I have landed a manual test to verify the same behavior.

> On compat, can we allay the concerns here with a fractional rollout (e.g., ~10% for a couple of releases) and a check-in at some point(s) before we go to 100%
The plan is to do a cautious-style Finch rollout, rolling out by increasing percentages of stable (like Stable 10%), before completely rolling out to Stable 100%.

I support a Finch rollout, but are there really compat concerns? Or more "user expectation" concerns?
 

Let me know if you have any more questions!
Thanks,
Kyra


On Wed, Feb 19, 2025 at 3:34 PM Tab Atkins Jr. <jacka...@gmail.com> wrote:
On Wed, Feb 19, 2025 at 3:44 AM Yoav Weiss (@Shopify)
<yoav...@chromium.org> wrote:
> Could the relevant spec language live in a PR? Having such language would make it easier to evaluate the gap between the current CSS spec and the ability to specify this behavior in an interoperable way.

The current appendix should describe the behavior in sufficient detail
for that purpose: it details exactly how to construct the caching key
and what keys to add, using the specific HTML terms (origin, site)
that we're relying on. Official spec text would just be slightly more
precise with its terms, but not, afaict, in a way that would affect
implementability.

Re-reading through this, what I'd love to see is:
* An HTML PR that properly integrates the "Whenever a navigation is triggered from within a page" parts of that appendix  (maybe as part of "navigate a navigable". Domenic would know for sure), and defines "visited history" as a set owned by the user agent.
* Define a "can show visited state" (or some other name) exported in algorithm in HTML that makes use of the above and replaces the "When determining if a link element" parts of the appendix.
* Refer to all that from an appendix in CSS until a time when the CSSWG feels comfortable enforcing this instead of the current fuzzy set of mitigations.
 

This is already more detail than what is specified for our *existing*
:visisted behavior, fwiw, which just exists in an MDN page and still
leaves many precise details (such as exactly what selectors are
allowed) to the imagination.

That's a good point. But we should aim to improve our standards.
 

~TJ

Yoav Weiss (@Shopify)

unread,
Feb 24, 2025, 5:15:23 AMFeb 24
to blink-dev, Yoav Weiss, Kyra Seevers, blink-dev, Domenic Denicola, jacka...@gmail.com
LGTM1

Talking to Tab and Kyra off list, I'm now convinced that the current spec is Good Enough™ (for now).

There are a couple of questions to be answered:
* When does the insertion to the "visited set" happen?
* What navigations are considered from "within a page"? 

However, there's no current implementation consensus on the answers to these questions.
The team seems committed to working towards alignment across implementations there after shipping, so I'm convinced we shouldn't block shipping this on precise specifications that won't necessarily help progress towards interop.

Chris Harrelson

unread,
Feb 24, 2025, 11:16:28 AMFeb 24
to Yoav Weiss (@Shopify), blink-dev, Kyra Seevers, Domenic Denicola, jacka...@gmail.com
LGTM2

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.

Daniel Bratell

unread,
Feb 25, 2025, 2:16:04 AMFeb 25
to Chris Harrelson, Yoav Weiss (@Shopify), blink-dev, Kyra Seevers, Domenic Denicola, jacka...@gmail.com
Reply all
Reply to author
Forward
0 new messages