Mozilla

privacy-related changes coming to CSS :visited

For more information about this, have a look at David Baron’s post, the bug and the post on the security blog.

For many years the CSS :visited selector has been a vector for querying a user’s history. It’s not particularly dangerous by itself, but when it’s combined with getComputedStyle() in JavaScript it means that someone can walk through your history and figure out where you’ve been. And quickly – some tests show the ability to test 210,000 URLs per minute. At that rate, it’s possible to brute force a lot of your history or at least establish your identity through fingerprinting. Given that browsers often keep history for a long time it can reveal quite a bit about where you’ve been on the web.

At Mozilla we’re serious about protecting people’s privacy, so we’re going to fix this problem for our users. To do so we’re making changes to how :visited works in Firefox. We’re not sure what release this will be part of yet and the fixes are still making their way through code review, but we wanted to give a heads up to people as soon as we understood how we wanted to approach fixing this.

These changes will have some impact on web sites and developers, so you should be aware of them. At a high level here’s what’s changing:

  • getComputedStyle (and similar functions like querySelector) will lie. They will always return values as if a user has never visited a site.
  • You will still be able to visually style visited links, but you’re severely limited in what you can use. We’re limiting the CSS properties that can be used to style visited links to color, background-color, border-*-color, and outline-color and the color parts of the fill and stroke properties. For any other parts of the style for visited links, the style for unvisited links is used instead. In addition, for the list of properties you can change above, you won’t be able to set rgba() or hsla() colors or transparent on them.

These are pretty obvious cases that are used widely. There are a couple of subtle changes to how selectors work as well:

  • If you use a sibling selector (combinator) like :visited + span then the span will be styled as if the link were unvisited.
  • If you’re using nested link elements (rare) and the element being matched is different than the link whose presence in history is being tested, then the element will be drawn as if the link were unvisited as well.

These last two are somewhat confusing, and we’ll have examples of them up in a separate post.

The impact on web developers here should be minimal, and that’s part of our intent. But there are a couple of areas that will likely require changes to sites:

  • If you’re using background images to style links and indicate if they are visited, that will no longer work.
  • We won’t support CSS Transitions that related to visitedness. There isn’t that much CSS Transition content on the web, so this is unlikely to affect very many people, but it’s still worth noting as another vector we won’t support.

We’d like to hear more about how you’re using CSS :visited and what the impact will be on your site. If you see something that’s going to cause something to break, we’d like to at least get it documented. Please leave a comment here with more information so others can see it as well.

Posted by on at

176 comments

Comments are now closed.

  1. evrix wrote on June 27th, 2011 at 12:20 pm:

    if anyone cares, I addeda bkmklet with this javascript and it seems to work in ff 5.0 on xp
    javascript:(function(){var%20newSS,%20styles=’a:visited%20{color:%20white;%20background-color:%20white;%20display:%20none}’;%20if(document.createStyleSheet)%20{%20document.createStyleSheet(“javascript:’”+styles+”‘”);%20}%20else%20{%20newSS=document.createElement(‘link’);%20newSS.rel=’stylesheet’;%20newSS.href=’data:text/css,’+escape(styles);%20document.documentElement.childNodes[0].appendChild(newSS);%20}%20})();
    I just added “color:%20white;%20background-color:%20white;%20″ right before “display:%20none”, which may be safely removed
    links with photos still show, but the related text gets *hidden*

  2. Jason Featheringham wrote on July 2nd, 2011 at 3:47 pm:

    This seems innately backwards. Why wouldn’t you just filter getComputedStyle() for visited links instead? Poor judgement from my perspective.

    1. evrix wrote on July 3rd, 2011 at 11:45 am:

      I just modified a bookmarklet working on previous versions and not made by me, I’m not so into js.

      ps: sorry for looong script line.

  3. Julian wrote on July 3rd, 2011 at 9:33 am:

    I’m fine with that, but could you please tell me, how do I hide visited links now?

    1. evrix wrote on July 5th, 2011 at 1:05 am:

      just let your bookmark bar be shown and add the bookmarklet to it (i.e. add a bookmark with a name like “delete visited” and the code in place of the address), go to any webpage and click on the bookmark: visited links should hide or became white.
      to all: ‘m not a javascript programmer, as a matter of fact I’m not a javascript anything :), so any suggestion will surely do a better work

    2. evrix wrote on July 5th, 2011 at 1:07 am:

      @louis
      Some css tags seem not to be any longer allowed in conjunction with visited links, did I miss something?

      1. louisremi wrote on July 7th, 2011 at 5:39 am:

        I mean you can still hide links by using the same color and background-color. As the article states, it isn’t possible “display: none;” for instance.

  4. Julian wrote on July 7th, 2011 at 7:47 am:

    Evrix
    That bookmarklet doesn’t work for me at all.

    Luisremi
    I would like to hide them, set them to “DO NOT DISPLAY”
    And if I cant do that with CSS like then how do I do it?
    I don’t have the time, nor knowledge necessary to make my own extension (and if the functionality is removed, then is there any other functionality to substitute that?).

  5. Moon wrote on July 11th, 2011 at 9:40 pm:

    Evrix,

    Thank you for trying to help! But that bookmarklet isn’t working for me either. I did exactly as you instructed, but the links do not change at all when I click on the bookmarklet I created.

    Is it working for anyone else?

    (By the way, I just installed Chrome to see if it replaces this lost functionality. Apparently, similar restrictions have been put in place in recent versions of Chrome, so that’s not an option for us.)

  6. ben wrote on July 13th, 2011 at 1:30 am:

    Suggestions:

    1) Give us a switch to turn the new behavior of.
    2) Allow local “url(‘data:image/png;base64,…)” style changes to “background-image”.
    3) Allow changes to “background-color”.
    4) Provide us with a list of elements which can still be changed (the ones mentioned in “https://developer.mozilla.org/en/CSS/Privacy_and_the_:visited_selector” don’t work – except for “color”).
    5) Give us samples of sites employing the pre 4.0 “security hole”.

  7. Luis wrote on July 24th, 2011 at 12:35 pm:

    Hi,
    I have a page with lots of links marked with images. This is the page:
    http://luis.impa.br/foto/index1.html
    As you can see, I use yellow box-shadows around img links. Since this does not combine with the blue/magenta usual borders for unvisited/visited, I wanted the box-shadow to change colors accordingly to the unvisited/visited status, but this don’t work. I tried everything I could think of using CSS :visited.
    Is my problem related to the issue described in this page? Is it solvable with CSS?
    Thanks!
    L.

    1. louisremi wrote on July 25th, 2011 at 12:47 am:

      Yes, our problem is likely to be related to the changes described in this page.
      Please read the article carefully.

  8. Nailgun wrote on August 4th, 2011 at 5:42 am:

    I understand that this is an issue, but the current proposed solution is preposterous.

    This is terrible for colorblind or color-impaired users of Firefox; it completely shuts them out. I would hope that timing attacks would be ineffective if the (simple) text-decorations like line-through, overline, and underline were re-enabled. I understand that this is a security issue, but if the hole is big to the point that it impinges upon accessibility, dev should just bite the bullet and do a bloody retool.
    I’m going to write an e-mail about this and see how far I get with it; there needs to be another way to visually distinguish different kinds of text other than color. It would be a similar hindrance if non-color-styles for regular ‘a’-links were disabled for whatever reason.

  9. Danny wrote on August 7th, 2011 at 12:25 pm:

    This ‘nanny’ approach is simply wrong but if you ‘have’ to do something to ‘protect’ the users then you could, for example, clear FF’s history every 24h by default…

    To f*ck up CSS specs is simply ridiculous… What is next? You won’t allow people to log into Facebook?

    Education is a better approach that don’t let me do my bloody job! Have some ‘Tip of the Day’ or ‘Advisory of the Day’ pop up telling the user to get a clue and clean his 5 years old history.

    1. chee wrote on October 26th, 2012 at 9:37 am:

      Wat. It seems a little barmy to prefer having your history to be deleted daily than there to be a limit on the styling of a:visited.

      In other notes, this doesn’t “f*ck” up CSS specs. Let’s look at the css2 spec together.
      http://www.w3.org/TR/CSS2/selector.html#link-pseudo-classes

      “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. See [P3P] for more information about handling privacy.”

      This is actually in keeping with the spec, and slightly kinder than what the spec allows for.

  10. Axel wrote on August 8th, 2011 at 1:06 am:

    Gimme a switch!

    I have been warned.

    Axel

  11. Pingback from Mozilla Firefox 4 Final oficial a partir del 22 de Marzo :Luctus on September 2nd, 2011 at 2:26 pm:

    [...] pone su privacidad en primer lugar, se corrigen algunos fallos que permitían a los chicos malos husmear y exponer el historial del navegador.Nuevos valores [...]

  12. ilPestifero wrote on September 26th, 2011 at 3:39 am:

    Great work for our privacy.
    Thanks mozilla!

  13. Reason A Bubble wrote on October 5th, 2011 at 3:27 pm:

    I guess they aren’t reading the comments.

    The consensus seems to be that some sort of opt in toggle would be preferable to us being told “this is what you want, this is what you get”.

    I found the comment regarding the issue this creates for colour blind people to be very relevant.

    The road to hell is paved with good intentions.

    1. Christopher Blizzard wrote on October 7th, 2011 at 7:06 am:

      Sorry, sometimes we miss comments. We’re not ignoring, just really busy sometimes.

      Let me check with David Baron, who wrote the original patch. (It actually might be a huge amount of work to support this, to be clear.)

    2. Christopher Blizzard wrote on October 7th, 2011 at 7:09 am:

      Also is there a bug on file about this? It would help a lot.

      cc me and drop me mail – blizzard@mozilla.com

  14. Moon wrote on October 6th, 2011 at 8:37 pm:

    Agreed. I think the folks at Mozilla aren’t bothering because people aren’t jumping ship over this.

    Chrome has some of the same dictatorial policies, you see.

    Come on, Mozilla. At least add the option in about:config. I can’t think of a single excuse for you to remove important Firefox functionality unilaterally and not even allow an advanced user to reinstate it.

    If someone else can, I’m all ears.

  15. Lila wrote on October 7th, 2011 at 7:20 am:

    There are lots of innocent uses of :visited, none of which are supported by FF 7, it seems. I understand the privacy concern, but why target the problem at the CSS-level? I use :visited to show users which parts of a website they have already been to, by changing the background-color of the link. Looks like now I need to change the text itself to provide this information – i.e. HOME (visited). Not the most elegant way – unless, of course, you use JS. Lots of JS. Which opens up all the JS-related security issues, of course.

    So, for security reasons, you are forcing people away from using just HTML and CSS to using javaScript to achieve the same effect? Please tell me this is a joke.

    1. chee wrote on October 26th, 2012 at 9:30 am:

      You can still use background-color to style the visited links.
      You cannot use JavaScript to determine which links have been visited.

      The opposite of what you think happened happened.

  16. LeftEarofCorn wrote on October 7th, 2011 at 2:33 pm:

    I used display:none on visited links via bookmarklet for image galleries to know what images I’ve already viewed. When reviewing thousands of rather similar photographs for a job, it is terribly cumbersome to keep track any other way. With no about:config option to toggle this terrible new behavior, I had to roll back to FF3.

  17. Moon wrote on October 7th, 2011 at 4:35 pm:

    P.S. Why are comments posted out of order? I look like a real douchebag having apparently posted *after* that mozilla dev did.

    1. Peter da Silva wrote on October 8th, 2011 at 4:39 am:

      They aren’t out of order. They’re nested but the nesting is kind of subtle gray boxes. The dev posted as a reply to the message, you posted a reply to the thread.

      1. Moon wrote on October 9th, 2011 at 4:38 am:

        How odd. I don’t see any gray boxes or nesting (using latest version of FF). Perhaps it’s something unusual about my setup.

        I’ll leave it at that; don’t want to derail this thread.

  18. Moon wrote on October 9th, 2011 at 8:15 am:

    I filed a bug report here: https://bugzilla.mozilla.org/show_bug.cgi?id=693164

    A Mozilla developer changed the status of the bug to Resolved (Invalid). I don’t know if he bothered to read the comments on this page, but it seems at least one developer does not deem this to be a problem.

    If you disagree, feel free to add to the discussion there.

  19. David P wrote on October 12th, 2011 at 4:33 pm:

    Why are transparent colors and changes to border-styles not allowed? Is there still work being done on this problem?

    I don’t understand why we can’t just have getComputedStyle() lie about everything including display and positioning, behaving as if the link was not visited. Maybe it’s a performance issue, having to keep track of a ‘true’ DOM layout and a ‘fake’ one, or in having to generate the ‘fake’ DOM element hierarchy on demand.

    If nothing else, at least let user styles have the freedom to work with visited links as we like. I totally support the above posted Bugzilla bug. This is still causing REAL users and loyal followers a great deal of pain.

  20. Bernd Schneider wrote on November 8th, 2011 at 11:41 am:

    Let me start with saying that I’m not a developer but a webmaster who prefers to focus on the content, and not on fixing code bugs. I know relatively little about CSS, but as I’m running a completely hand-made website I won’t get any dedicated support on it either.

    Visited external links look horrible on my site now, because I used the same basic GIF background image that so far changed its color together with the link. Now it is teal vs. yellow besides white on black. The maximum penalty if you ask me.

    I have to explain my visitors
    1) Why it looks so bad.
    2) Why I don’t do anything about it.
    3) And perhaps to those who read something about the privacy subject I may have to justify why I was using “evil code” to sniff out their browser history (which of course I have never done).

    Options for me to fix the issue:
    1) Develop a whole new color/image scheme in which the background images always keep their color and still look good next to the link.
    2) Ditch all tags for external links. I needed a couple of days to work them into the code. It will take just a few clicks to disable the extra usability in the style sheet.
    3) Other options?

  21. roger21 wrote on November 15th, 2011 at 4:54 am:

    THAT SUCKS

    i had a greasmonkey script that allowed me to open all at once the unvisited link from a reddit page using getComputedStyle now it doesn’ work

    i had a stylish bstyle that changed the font weight of link from bold for unvisited to normal for visited (using :visited of course) it was very conveniant to highlight unvisited links and downlight visited ones now it doesn’t work

    THAT SUCKS

    at least ther could be a addons or something to bypass that THAT SUCKS

  22. Pingback from How do I change the CSS of child of an a-element | SeekPHP.com on November 15th, 2011 at 10:37 am:

    [...] But then, you shouldn’t rely on :visited. Indeed, it can be used for history sniffing, and browsers will probably end up removing support for most CSS properties that change layout (such as display), just like Firefox already does. [...]

  23. Christos Georgiou wrote on November 17th, 2011 at 12:13 am:

    Please: add an option in about:config that allows the :visited CSS functionality as it was; we have been warned about the security issues.

  24. armin wrote on November 24th, 2011 at 6:33 am:

    about:config
    CSS functionality:visited

    doesn’t work

    1. Bernd Schneider wrote on November 24th, 2011 at 7:24 am:

      and doesn’t help because it’s an individual setting.

  25. heike wrote on December 19th, 2011 at 8:39 am:

    Oh, Klasse! ‘<
    Ich habe jetzt einen ganzen Nachmittag mit dem Versuch vertrödelt besuchte Links im FF unsichtbar zu machen – und eben zu meinem Entsetzen diesen Artikel gefunden.
    Wahnsinnsidee, Mann! Was soll der Mist?! :@

  26. popitto wrote on January 23rd, 2012 at 9:02 am:

    did you find a solution for this problem? i’m using FF 9.0.1 and i found an entry in about:config (layout.css.visited_links_enabled) it was ‘true’ so i changed it to ‘false’ but nothing changed! the color of the visited links are still the same (different from the visited ones)!

  27. brenda wrote on March 25th, 2012 at 9:52 pm:

    I am taking a college course an this has crashed a lot
    I cant have that and lose all my work I updated the latest firefox there is no bar
    to let you print what am I supposed to do can you give me any suggestions

    1. Eric wrote on March 26th, 2012 at 10:54 am:

      What does that have to do with CSS security?

  28. estrella wrote on October 8th, 2012 at 6:29 pm:

    no comment

  29. Serguei wrote on November 24th, 2012 at 6:37 pm:

    May be there are any setting in Mozilla browser to switch off CSS privacy for trusted sites?

  30. Moon wrote on November 30th, 2012 at 4:03 pm:

    All you people commenting really should consider posting your comments on the official bug report here:

    https://bugzilla.mozilla.org/show_bug.cgi?id=693164

    Posting here accomplishes nothing. Posting there raises the profile of the problem.

1 2 3

Comments are closed for this article.