By Andrew Tetlaw

Mozilla to Tackle Browser CSS History Privacy Leak

By Andrew Tetlaw

All browsers can be exploited to reveal the websites that you’ve visited; that is, all the websites in your browser’s history list. The technique is fiendishly simple. Apply a rule to a link using the CSS :visited selector that either applies a background image or a color. Then, either query the property with JavaScript to see if the value was applied, or make a unique URL to the background image for each link you’re testing that records the information server side. There are ready-made libraries available that can check large numbers of URLs very quickly — I’m talking hundreds of thousands per minute.

Well, Mozilla has announced a strategy they’re adopting to tackle the issue, which will have some repercussions for web designers. And they’re hoping other browser makers will follow suit. It involves three major changes to the Mozilla codebase that will affect browser behavior:

  1. Visited links can only be differentiated by color: foreground, background, outline, border, SVG stroke, and fill colors.
  2. All style rules for visited and unvisited links will be resolved at the same time, and before any link styles are applied.
  3. When JavaScript is used to query the computed style of links, only the unvisited style values will be returned.

Surprisingly this strategy is compliant with the CSS 2.1 specification, which states:

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.

I have to admit I was unaware of how big the problem is and how easy it is to exploit. But, after doing some reading on the subject, it seems like the right action to take. I’m also surprised that it has taken this long for a browser vendor to address the problem. I hope Mozilla’s example catches on.

In the comments to the Mozilla post people are already complaining that they often use background images to style visited links, and that color-blind users will be disadvantaged. What do you think of this strategy? Will any of your favorite CSS techniques have to be changed? Will this really have a big effect on your work or will it be easy to accommodate?

  • This issue has been around for many years, but I’m not convinced anyone’s created a nasty exploit. You can only find out whether a user has visited a specific website — you can’t associate it with an individual unless the user’s logged in.

    At worst, I can see this being used for marketing purposes. For example, a visitor to could shown a special offer if they recently visited

    The second two fixes seem reasonable and I’m sure it’s all you need. The first rule seems overly restrictive.

    • SixDegrees

      Charles Johnson at “Little Green Footballs” has used this exploit to track which of his visitors have visited blogs he doesn’t approve of. He normally bans those users from his site when they’re discovered. A problem with this, among others, is his habit of loudly denouncing specific articles published by the sites he finds offensive, which inevitably drives his own readers to peek at the article and thereby open themselves up to being banned.

      While this isn’t of any earth-shattering importance, it does represent an invasion of user privacy.

  • Anonymous

    As others have said in comments on that mozilla blog, they should only limit the styling on visited external links.

  • W2ttsy

    apart from referrers can someone explain how a javascript on a new page would be able to traverse the history of pages it wasnt executed on or attached to? surely the XSS models most browsers have would prevent this?

    pity mozilla are moving to block this, it would have been a good way for developers to add simply (even though it may be ineffective) analytics to their site…

  • @W2ttsy
    All JavaScript is doing is analysing what’s happened to a visited link on your page. Let’s assume you want to track whether one of your visitors has previously been to SitePoint. You add this code to your page:

    <a href="" id="sp">SitePoint</a>

    You can now have the following CSS:

    #sp:visited { background-image: url(hit.php); }

    If you’d visited SitePoint, hit.php would execute. You could then do anything in the server-side code or use JavaScript to determine whether hit.php was the background image applied to the #sp link.

    Clever isn’t it!

  • SouthernUS

    One can still help out the color-blind user by styling a change to a font instead of only a color change to indicate a visited link.

  • arts-multimedia

    If you’d visited SitePoint, hit.php would execute. You could then do anything in the server-side code or use JavaScript to determine whether hit.php was the background image applied to the #sp link.

    Wow, that’s creepy! :-)
    I don’t mind the change, it will not effect my websites as I genrally do not rely on images to mark visited links, although I probably will have 1 or 2 sites. Not really

  • littletikiRobot

    OK, what do you do with the javascript then? Oh, and what’s the code in hit.php?

  • Jason

    One thing I never understood was why visited links were important. I never cared if I already visited a given site…if I need the information from that site (or page) I would visit it again… I actually do not remember the last site I coded where the visited and unvisited styles were made different…

  • Why not have the browser load the image whether it needs it or not? That would foil the privacy breach and legitimate use.

  • Tim

    Seems a bit limited because you have to test for every “link” out there, not just every domain. As Craig said, it might be useful for testing if a user has been to a competitor site, but you still have to check for a specific link. is different to which is different again to, etc, etc

  • OsakaWebbie

    If background-image was limited to URLs that are actually images (file extension in an approved list like jpg/gif/png/etc. – i.e. non-executables), wouldn’t that solve the problem without preventing background-image altogether for visited links?

  • Pavel Lang

    As others have said in comments on that mozilla blog, they should only limit the styling on visited external links.

    I agree with this, but I’m also compliant with fact that only explicitly defined pages can be watched via this exploit. In fact this again introduce divergence between browsers, if this behavior has roots in CSS 2.1, it should be done in all browsers (Internet Explorer not excluded :-))

    In fact, this new behavior (or security enchantment) cannot drastically change readibility of top visited sites, because color and other safe CSS values will be respected by browser renderer engine (for price of some if statements in DOM code)

    Correct me if I’m wrong in something…

  • Does seem like a lot of effort to go to to elimit a fairly minor exploit – it’s not like your security is at risk from this, it’s just a minor point of privacy, no more serious than the ability of shim trackers in HTML email, things like that.

    All the same, I won’t really shed a tear if it’s implemented – no loss either way really. I suppose the one thing is that if JS queries do return all links as unvisited, it will remove the only way of determining programatically which links are visited or unvisited, because none of the object models have that information. But I don’t think that really matters too much, I mean, why would you need to know for any legitimate purpose?

  • @OsakaWebbie

    If background-image was limited to URLs that are actually images

    That won’t work, I’m afraid. It’s easy enough to configure a web server to run a server-side application whenever a file is requested. To the outside world, it’ll still look like a graphic and have the right file extension.

  • davidcroda

    As the OP mentioned there are already libraries with hundreds of thousands of links. It’s not like computer’s can’t process lists of millions of of sites. I am sure someone who is trying to exploit this would be able to find a way to make it useful. I am glad Mozilla is moving to stop this.
    I agree I never really understood why it was so important to track visited links. The only sites it is useful for me on is search engines like google where I am trying to find a past search result.

  • Grover Saunders

    Maybe I’m missing something, but wouldn’t the third change obviate the need for the first and second change?

  • XLCowBoy

    I wouldn’t say it’s really that minor an exploit.

    Running server-side scripts mean they can track everything from your IP, location, and browsing history. With the right combination, they can possibly piece together enough data for identity theft.

Get the latest in Front-end, once a week, for free.