Firefox sessionstore.js and privacy

Firefox, much like other browsers, has been allowing you to restore browser “sessions”, which will restore the state of any page loaded, url, referrer, tab location, title, form data, the size of the rendering, font zooming, scrolling done on the page, closed tabs, and other fun things.

Personally, I find this to be an extremely neat feature. I use it on a regular basis, since I’ll often be trigger-happy on my close tab hotkeys. So it’s all nice and dandy, right? Well, the problem is that Firefox obviously can’t tell what data is sensitive and what isn’t. It will assume a form field marked as password type to be bad to include, but could there be other concerns? The answer is: Yes. And unless users are aware, this could be potentially bad. Here we’ll take a look at what is stored by the browser, and how we can observe this.

To test this, I had my VM with Procmon and a clean copy of the latest Firefox. Here are the steps taken to showcase this feature:

  • Open procmon, filter by firefox.exe
  • Open firefox
  • Browse to (This was *entirely* random, as it was the first page I found with a Paypal donate button)
  • Click on the “Donate” Paypal button
  • Fill out some random information in the Paypal form for making a transaction (Note that I had not previously logged into Paypal from this machine, thus getting a form to do the full transaction)
  • Open a new empty tab
  • Close the Paypal tab which contains the sensitive information, such as credit card number
  • Close Firefox
  • Search Procmon for sessionstore.js

At this point we check out what is contained in the sessionstore.js file.

Contents of sessionstore.js
The sessionstore.js is a simple JSON file, hence the .js extension (It contains no actual JavaScript code). It is a serialized state of the windows, closed windows, tabs, history, and closed tabs which is persisted on a regular basis. Here are the contents, having followed the above mentioned steps:

Here are some things we can notice that the file contains:

  • A list of open windows
    • A list of tabs
      • Tab entries
    • Index of selected tab
    • Closed tabs
      • Tab entries
    • Width
    • Height
    • Screen X
    • Screen Y
    • Size mode
    • Title of window
    • Flag for if the window should restore
  • Index of window selected
  • A list of closed windows
    • A list of tabs
      • Tab entries
    • Index of selected tab
    • Closed tabs
      • Tab entries
  • Session information
    • State of the session
    • Time stamp for last update
    • Time stamp for when the session started
    • A flag for if the session crashed
  • Scratch pads (A developer tool)

We notice that the structure is two lists of windows(Open and closed), which contains two lists of tabs (Open and closed), and then a bit of extra data. Each tab then has a whole substructure to itself that is duplicated. If the page is no longer active (It may have been browsed away from), it will contain this:

  • URL
  • Title
  • ID
  • Document shell ID
  • Document identifier

But if it is active, it will contain a bunch more:

  • URL
  • Title
  • ID
  • Document Shell ID
  • Referrer
  • Document identifier
  • A list of children
    • URL
    • ID
    • Document Shell ID
    • Owner(base64)
    • Documentation identifier
    • Scroll state
  • Form data
  • Scroll state

All this will of course be a lot more complex to look at when more complex tab setups and browser history is present. This is by far the most simple I could make it by only just browsing enough to show the major aspects of it.

Private information in the file
What you may have noticed by now, if you look at the big bit of JSON above, is that form data is included in the file. This is something to be aware of, if you type sensitive information in.

Specifically, this is the bit where you have to be careful:

As you can tell, the full form I was presented with at Paypal has been stored in clear-text on my drive despite closing the tab and the window. An unaware user could think at this point that because they can’t see the window, that the inputted data is gone for good. That is however not the case.

I’ve tested this with password fields. These are not stored, for good reasons. But it is clear that non-password fields may and will often contain information which you may not want to

Mitigation options
If you’re concerned with data that may be present inadvertently in this file, you have a few options for dealing with this

Using private browsing mode
The private browsing mode is probably overkill for many. The danger with this feature is that it is not made explicitly clear to the user what is being stored. But if you have sensitive information you want to hide from the local machine, you should be using this anyway.

This flag can be changed from the default value of true to ensure that if the browser crashes or otherwise unexpectedly closes, that it does not commit the sessionstore with this information. But this doesn’t disable the feature entirely.

browser.sessionstore.max_tabs_undo and browser.sessionstore.max_windows_undo
These two flags allow you to specifically set how many tabs and windows respectively are stored in cache. By setting these to 0, you can entirely disable this feature, causing no potentially sensitive information to be stored.

The manual approach
Another thing you can do, while not as foolproof, is to remove any information in form fields before closing a tab, which you do not want to be cached. While this works, it should be remembered that the possibility is still there if not careful! You can also clear private data from Firefox through the built-in options, which will clear this out. Again the problem becomes the fact it requires manual interaction, which depends on the user being aware of this information being cached.