Sharovatov’s Weblog

startpanic.com and :visited links privacy issue

Posted in browsers, privacy, security by sharovatov on 21 April 2009

Back in April 2008 I was blogging about Selectors API support in IE8 Beta 1 support and mentioned the security concern about :visited links – potential privacy theft.

The problem

This concern was risen long ago in CSS2.1 Spec (and also mentioned then in the following specs – CSS3 Selectors, Selectors API spec):

Note. It is possible for style sheet authors to abuse the :link and :visited pseudo-classes to determine which sites a user has visited without the user’s consent.

UAs may therefore treat all links as unvisited links, or implement other measures to preserve the user’s privacy while rendering visited and unvisited links differently.

The original bugzilla issue was reported back in October 2000, Stanford sameorigin whitepapers had this issue described in 2002, then lots of articles followed, and then Ajaxian had an article in 2007 which made this issue really popular.

And now we have http://startpanic.com with nice implementation of this approach – it has a txt database of some thousands URLs that are tested for being visited.

You can check the code – it’s pretty straight forward – links from the database are appended to the iframe where :visited links are displayed and others are hidden, then current style of the current link is checked and if it’s hidden, this link is appended to the big list of visited links.

Possible solutions

Basically, there’re some ways to resolve this issue:

  1. try to protect :visited links computed style access
  2. limit support of :visited
  3. don’t fix it, find a way around

Protect :visited links programmatically

That’s clearly useless. People were suggesting many solutions (which you can get round), like making getComputedStyle return default value for :visited links as if they are not visited – but you can make the case more complex, e.g.

a:link span {display: none;}
a:visited span { display: block }

and then use getComputedStyle to check the span; and all the proposed solutions were weak in some way. But even if you manage to make scripts unaware about the state of your links, there will always be a server-side attack vector – for those links that you want to check you can just specify a unique background-image pointing to some server-side tracking script, e.g.:

#alQaedaLnk:visited {background:url(http://www.cia.gov/track.pl); })

Like here, for example. So it clearly shows us that there’s no way (or it’s too troublesome) to fix this “issue” programmatically.

Limiting support for :visited

As I understood from the discussion with startpanic.com author, he wants to limit :visited support so that only links to pages to the same domain are applied with :visited pseudo class. But this would hurt user experience so much! First example that comes to my head is Google and other search engines – they all colour visited links differently so you can clearly see which pages you’ve already been on and which not. If same-domain policy is applied, all the links in Google search results will be plain blue. This sounds awful to me.

Guys from Stanford security group suggest applying :visited only to those links that were visited from the current domain. This approach was used in Firefox add-on called SafeHistory (it doesn’t work any more). So if you do a search in Google and visit some pages, :visited will be applied to these pages only in Google search results. So if you then do a search on MSN Live Search, all the links there will be plain blue and :visited won’t be applied to them. To me this solution looks weird as well. And Firefox developers said that it would be a problem to support this; and I don’t think other browser vendors will fix this privacy “issue” in that way. Keep on reading, I will explain why.

So from technical prospective the only easy solution would be to completely remove support for :visited pseudo class, which nobody will do because user experience will suffer and people will complain.

Best solution – find a way around

You may think – why not make :visited support configurable in the browser UI?  But that’s what all browsers already have! You can specify that you don’t want to keep history at all, you won’t see visited links anywhere, you will feel that you’re “safe” :).

Another solution – Private Browsing mode

Another nice option is to use Private Browsing mode that’s supported by all modern browsers IE8, Safari, Google Chrome (and then FF3.1 joined). When you visit a site that you don’t want to appear in the history – use Private Browsing mode and you’re safe.

Note: currently Google Chrome has a bug – it applies :visited pseudo class to links in Incognito Mode. However, the bug is fixed and the bugfix will be included in one of new updates.

“Private Browsing” browser feature is the only true solution to this issue.

Here’s a testcase. I visited both http://ya.ru and http://www.google.com links in IE8 InPrivate mode, then went to the testcase page and it didn’t tell anything as if I hadn’t visited these URLs.

When I followed the same process in Google Chrome “Incognito mode”, it showed that I visited both ya.ru and Google.com. This bug is fixed and will be updated in newer versions of Google Chrome.

And this issue is also fixed in FF3.1b3:

In comments Avdeev said that Safari in its Private Browsing mode (they call it Porn mode) didn’t show if the link was visited or not. Great stuff!

Update: It seems that Opera 10 will have Private browsing mode support as well – they are already choosing the name for it – and the most voted one is “Phantom mode” :)

Note: while I understand the whole concern about privacy, you shouldn’t forget that all search engines, adds providers and many many others gather statistics about your visits. When you’re in London (and other major cities), you’re being watched on CCTV constantly, does it bother you? Does this new world leave any space for privacy?

Links:

Share :
Advertisements
Tagged with: