When Firefox Fails You: Forensic Recovery of Lost Tabs on Linux
1. Introduction
I recently lost a Firefox window during shutdown, and unfortunately, it was not saved in the session restore. It was a window filled with extensive research, consisting of many tabs meticulously grouped. Losing it meant losing a significant amount of context and work.
2. Initial Attempts (and why they failed)
My first instinct was to use standard Firefox features. I checked “Restore Previous Session” and “Recently Closed Windows,” but the window simply was not there. Firefox had completely missed it during the shutdown sequence. These built-in features rely on the session state correctly persisting to disk during closure, which clearly had failed in my case.
3. Discovering Firefox Session Backups
Knowing that browsers maintain robust session states, I decided to dig into my profile directory to look for backups. On Linux, Firefox stores session data in:
| |
In this directory, you will typically find several files:
recovery.jsonlz4recovery.baklz4previous.jsonlz4upgrade.jsonlz4-*
These files serve specific purposes:
- recovery represents the current state right before a crash.
- recovery.bak is a previous snapshot of the state.
- previous is the state from the last clean shutdown.
4. The jsonlz4 Gotcha
My initial thought was to simply decompress these files. However, there is a significant gotcha: these are not standard LZ4 files. They contain a custom mozLz40\0 magic header. If you try to use the standard lz4 command line tool to decompress them, it will fail:
| |
| |
5. Decoding the Files Properly
To read these files, we need to bypass the custom header and decompress the raw LZ4 block. You can achieve this using Python. First, install the necessary Python bindings. On Gentoo, for example, you can emerge it:
| |
Then, you can use the following Python snippet to properly decode the file:
| |
By skipping the first 8 bytes, we extract the raw LZ4 block rather than an LZ4 frame, allowing the standard block decompression to succeed.
6. Extracting Useful Data
Once decoded, recovery.json reveals the complex session structure. The primary path to your tabs is:
windows -> tabs -> entries
To find the most recent URL and title for each tab, you must select the entry corresponding to the index property of the tab object. The entries array contains the history of that specific tab, and the current state is tracked by this index.
7. Converting to Markdown
To make the recovered session useful, my goal was to turn the raw JSON into human-readable Markdown. Here is a simplified approach to generate a Markdown outline of the session:
| |
This script produces output similar to:
| |
Handling tab groups can be tricky because the storage format is non-standard and varies by Firefox version or installed extensions. You might need to look for keys like groupId, extData, or attributes depending on your setup.
8. Results
After decoding and inspecting the files, the results were disappointing. The lost window was not present in recovery, recovery.bak, or previous.
Furthermore, I observed identical decoded sizes for both recovery and recovery.bak. This indicates that no new state was captured during the time the lost window was open. The conclusion is that Firefox never persisted that window to disk; it existed entirely in memory at the time of shutdown.
9. What Still Worked
Although the window’s structured session was gone, the individual pages were not completely lost. The Firefox history database (places.sqlite) still contained the URLs I had visited. You can query this database directly to salvage links:
| |
10. Lessons Learned
This experience highlighted several important lessons about browser sessions:
- Firefox session persistence is not atomic.
- Shutdown timing matters significantly; a rapid or forced shutdown might prevent the final session state from being written.
recovery.baklz4is often the best candidate for recovery since it might capture a state before a catastrophic failure or premature shutdown.- Always check multiple backup files.
- Session files are entirely recoverable with the right tools, despite the custom header.
- Consider periodic tab or session exporters for critical work.
11. Optional Improvements
To prevent this from happening again, there are a few strategies you can employ:
- Set up a cron job to snapshot the
sessionstore-backupsdirectory periodically. - Install browser extensions dedicated to reliable tab export and session management.
- Utilize filesystem-level snapshots (like btrfs or ZFS) for your home directory to easily roll back to a known good state.