Files
HackBrowserData/rfcs/004-firefox-data-storage.md
Roger d8032ac824 docs: rewrite readme, rfcs, and contributing (#555)
* docs: rewrite README, RFCs, and CONTRIBUTING
* docs: fix Linux storage labels in RFC-006 (Opera/Vivaldi swapped)
2026-04-06 00:16:47 +08:00

5.1 KiB

RFC-004: Firefox Data Storage

Author: moonD4rk Status: Living Document Created: 2026-04-05

1. Profile Structure

Firefox stores per-user data in profile directories beneath a platform-specific root (e.g. ~/Library/Application Support/Firefox/Profiles/ on macOS). Each profile directory has a random-prefix name like 97nszz88.default-release.

Profile discovery enumerates subdirectories of the root and accepts any directory that contains at least one known data file. Unlike Chromium (which looks for a Preferences sentinel), Firefox validation simply checks for the presence of any source file from the table below.

2. Data File Locations

All paths are relative to the profile directory.

Category File Format
Password logins.json JSON
Cookie cookies.sqlite SQLite
History places.sqlite SQLite
Download places.sqlite SQLite
Bookmark places.sqlite SQLite
Extension extensions.json JSON
LocalStorage webappsstore.sqlite SQLite

History, Download, and Bookmark all share places.sqlite but query different tables within it. Firefox does not support CreditCard or SessionStorage extraction.

The master encryption key is stored separately in key4.db (see RFC-005).

3. Data Storage Formats

3.1 Passwords (logins.json)

Passwords are stored as a JSON file with a top-level logins array. Each entry contains:

  • formSubmitURL / hostname — the login URL (formSubmitURL preferred, hostname as fallback)
  • encryptedUsername — base64-encoded, ASN1 PBE-encrypted username
  • encryptedPassword — base64-encoded, ASN1 PBE-encrypted password
  • timeCreated — creation timestamp in milliseconds

Decryption pipeline: base64 decode the field, parse as ASN1 PBE structure, decrypt with the master key.

3.2 Cookies (cookies.sqlite)

Cookies are not encrypted — values are stored in plaintext.

SELECT name, value, host, path, creationTime, expiry, isSecure, isHttpOnly
FROM moz_cookies

The database must be opened with journal_mode=off to avoid locking conflicts with a running Firefox instance.

3.3 History (places.sqlite)

SELECT url, COALESCE(last_visit_date, 0), COALESCE(title, ''), visit_count
FROM moz_places

The last_visit_date column uses microseconds since epoch.

3.4 Downloads (places.sqlite)

Downloads use the moz_annos annotation table joined with moz_places:

SELECT place_id, GROUP_CONCAT(content), url, dateAdded
FROM (SELECT * FROM moz_annos INNER JOIN moz_places ON moz_annos.place_id = moz_places.id)
t GROUP BY place_id

Download metadata is stored as a concatenated string: target_path,{json} where the JSON portion contains fileSize and endTime.

3.5 Bookmarks (places.sqlite)

SELECT id, url, type, dateAdded, COALESCE(title, '')
FROM (SELECT * FROM moz_bookmarks INNER JOIN moz_places ON moz_bookmarks.fk = moz_places.id)

The type field distinguishes URL bookmarks (1) from folders.

3.6 Extensions (extensions.json)

Extensions are read from the addons array. Only entries with location == "app-profile" are included (user-installed extensions). Fields extracted: defaultLocale.name, id, version, defaultLocale.description, defaultLocale.homepageURL, active.

3.7 LocalStorage (webappsstore.sqlite)

SELECT originKey, key, value FROM webappsstore2

The originKey column uses a reversed-host format: moc.buhtig.:https:443 represents https://github.com:443. The host portion is byte-reversed and dot-suffixed; the remaining fields are scheme and port.

4. Time Formats

Firefox uses inconsistent timestamp units across data types. All are Unix epoch-based.

Data Type Unit Conversion
Cookies (creationTime) Microseconds / 1,000,000
Cookies (expiry) Seconds direct
History (last_visit_date) Microseconds / 1,000,000
Downloads (dateAdded) Microseconds / 1,000,000
Bookmarks (dateAdded) Microseconds / 1,000,000
Passwords (timeCreated) Milliseconds / 1,000

5. Key Differences from Chromium

Aspect Chromium Firefox
Profile naming Named directories (Default, Profile 1) Random-prefix (97nszz88.default-release)
Profile detection Preferences sentinel file Any known source file present
Password storage SQLite (Login Data) JSON (logins.json)
Cookie encryption Encrypted with master key Plaintext
Shared database Separate files per category places.sqlite shared by History/Download/Bookmark
LocalStorage LevelDB SQLite (webappsstore.sqlite)
CreditCard support Yes No
SessionStorage support Yes No
Encryption scope Passwords, cookies, credit cards Passwords only (see RFC-005)
RFC Topic
RFC-005 Firefox NSS encryption and master key derivation
RFC-008 File acquisition and platform quirks