Skip to content

[selectors] Solve :visited once and for all #3012

@tabatkins

Description

@tabatkins

In w3c/css-houdini-drafts#791 @deian explains a new channel for high-bandwidth leaking of :visited state by observing repaints with the Houdini Paint API. There doesn't appear to be a reasonable way to shut this down under the current regime of partial-censoring of :visited - the current fix for Chrome is to just disallow the paint() function from being used at all on any <a> element or its descendants.

We really need to finally define a sensible model of :visible-state visibility, based on what information would have already leaked to the page via standard, unpluggable channels; then we can finally drop all the silliness around :visited and just treat it as a plain, ordinary pseudo-class that allows all properties to be used in the standard fashion.

  1. At minimum, same-origin visitedness is always visible to the page, as the server can track its own cross-links, assuming standard tracking mechanisms exists (cookies, sufficiently high-entropy user identification, etc). So all same-origin links should report :visited.

  2. Cross-origin inbound links are always visible to the page if the Referer header was sent in the request.

  3. Cross-origin outbound links are always visible to the page if the user visited that link from this origin, as there are a multitude of ways to track outbound links (JS auditing, <a ping>, link shorteners, etc).

  4. Any others?


If a link matches one of the conditions above, and is visited, it's allowed to match :visited; otherwise it never matches :visited. So, what's the cost/benefit of each of the conditions above?

1 is easy to apply and non-controversial. It also probably represents at least half of the benefit of :visited styling for the user - they can tell when they've already visited a given page on a site.

But I don't think it's a whole lot more than half - there is a lot of benefit to knowing what links you've visited from a given page, regardless of origin. (Think of clicking thru each of a list of outbound links, such as in a forum post, or in Google search.) So I think 3 is most of the rest of the benefit, but probably the most controversial in terms of theoretical privacy (even if it's nil in practical privacy for the vast majority of users). I think it's reasonable for browsers to nix this condition if the user is blocking script, as that's the primary tracking mechanism.

I think 2 is of relatively minor benefit, but it lies inbetween 1 and 3 in terms of privacy leaking. Some UAs do offer the ability to block Referer, and of course they would then block this visitedness channel, but otherwise it's common and not a big deal. It's just that most cross-origin pages won't have a link back to the page you visited from; the exception is things like weird cross-site web puzzles, or old-school webrings.

Are there any other conditions that would allow us to safely expose :visited state unreservedly?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions