Skip to content

SecurityRonin/browser-forensic

Repository files navigation

Docs Rust 1.80+ Platform License: Apache-2.0 Sponsor

CI Fuzz unsafe forbidden security: cargo-deny

browser-forensic

Parse Chrome, Firefox, and Safari — and embedded-Chromium apps — into one JSON timeline. Detect history clearing. Carve deleted records. No runtime deps.

Browser artifacts are present in almost every investigation — they reconstruct the user's timeline, expose credential exposure, and often reveal the delivery mechanism for an attack. The problem is tooling: most parsers require Python, lock you to Windows, or ignore the forensically interesting question of whether the evidence was tampered with.

br4n6 is a single static Rust binary. Point it at a browser database and get JSON. Point it at a profile directory and get a full triage report with integrity indicators and carved deleted records. Point it at an evidence tree and it sweeps out every browser and every embedded-Chromium app (Electron, WebView2, CEF) it can structurally identify.

cargo install --git https://github.com/SecurityRonin/browser-forensic browser-forensic-cli
br4n6 history /path/to/Chrome/Default/History --format jsonl | jq 'select(.attrs.url | test("google.com"))'

Install

From source

git clone https://github.com/SecurityRonin/browser-forensic.git
cd browser-forensic
cargo build --release
./target/release/br4n6 --help

Three Things You Do With This

Reconstruct the full browser timeline

# Chrome history — last 30 days, sorted by time
br4n6 history /path/to/Chrome/Default/History --format jsonl \
  | jq -r '[.timestamp_ns, .attrs.url, .attrs.title] | @tsv' \
  | sort | tail -100

# Firefox — same command, different path
br4n6 history /path/to/Firefox/Profiles/abc.default/places.sqlite --format jsonl

Every supported browser produces the same BrowserEvent JSON schema. Your downstream analysis pipeline doesn't need to know which browser produced the data.

Detect history clearing and tampering

br4n6 integrity /path/to/Chrome/Default/History --format jsonl
{"HistoryCleared":{"browser":"Chromium","path":"/path/to/History","detected_at_ns":1700000000000000000}}
{"AutoIncrementGap":{"path":"/path/to/History","table":"urls","max_rowid":2,"auto_increment":847}}
{"VisitIdGap":{"path":"/path/to/History","expected_id":3,"found_id":851}}

Three indicators in under 100ms. The sqlite_sequence table recorded 847 URL insertions; only 2 rows remain. IDs jump from 2 to 851. The user cleared their history — and this database says exactly when the last visible record was written.

Carve deleted records from SQLite free pages

br4n6 carve /path/to/Chrome/Default/History --format jsonl

SQLite marks deleted rows as free pages rather than overwriting them immediately. br4n6 carve walks the freelist chain, scans each free page for URL patterns, and returns whatever survived (via the published sqlite-forensic recovery engine). Combine with br4n6 integrity to establish what was deleted and what was recovered.


What's Different

browser-forensic now matches the artifact breadth of the mainstream browser-history tools — including web storage (Local / Session Storage, IndexedDB) and embedded-Chromium container discovery — and adds forensic depth those tools do not carry: integrity/tampering detection, free-page carving, WAL recovery, memory scanning, and an embeddable Rust library.

Capability browser-forensic Hindsight Browser-Reviewer
Chrome / Chromium
Firefox
Safari
Web storage (Local / Session / IndexedDB)
URL / cookie interpretation
Embedded-Chromium container discovery
Integrity / tampering detection
SQLite free-page carving
WAL recovery
Memory byte-pattern scanning
Correlated XLSX / SQLite export
Embeddable library
Runs on Linux / macOS / Windows Windows only

Reflects each tool's documented feature set as of mid-2026. Hindsight parses Chromium (and, more recently, Firefox) profiles in Python; Browser-Reviewer is a portable Windows GUI/CLI for Firefox and Chromium.


Browser Coverage

Artifact Chrome / Chromium¹ Firefox Safari
History
Cookies
Downloads
Bookmarks
Extensions / Add-ons
Autofill
Login Data (no passwords)
Cache
Session State
Preferences
Top Sites
Profile Metadata (Local State)
Web Storage (Local / Session / IndexedDB)
Integrity indicators
SQLite free-page carving
WAL recovery

¹ Chromium-family covers Chrome, Edge, Brave, Opera, Vivaldi, and Arc — one engine, one set of parsers.


Web Storage

br4n6 storage reads the three web-storage backends the browsers use, emitting the same BrowserEvent schema as every other artifact:

br4n6 storage /path/to/Chrome/Default --format jsonl
  • Chromium Local / Session Storage — LevelDB, decoded through the published leveldb-forensic crate.
  • Chromium IndexedDB — LevelDB-backed; values are Blink/v8-serialized and surfaced as opaque raw records rather than a fabricated decode.
  • Firefox web storage — plain SQLite (webappsstore.sqlite and storage/default/*/idb/*.sqlite).

Each event carries a storage_type attr (local_storage, session_storage, indexeddb) so downstream filtering stays simple.


Container Discovery

Modern desktop apps embed Chromium — Slack, Teams, OneDrive, and hundreds of Electron / WebView2 / CEF apps keep the same history, cookies, and web-storage databases a browser does. br4n6 browsers --sweep recursively walks an evidence tree, identifies each container by its structural profile markers (backed by forensicnomicon::browser_profiles), and attributes it to the owning app:

br4n6 browsers --sweep /mnt/evidence/Users/jsmith --format jsonl

The sweep reports every browser profile and embedded-Chromium container found, with the app name, vendor, and how it embeds Chromium (Browser / Electron / WebView2 / Cef). A profile-shaped directory that matches no catalog entry is still reported, generically labelled — nothing is silently dropped.


Integrity Checks

br4n6 integrity detects raw structural anomalies — observable facts about the database, not forensic conclusions:

HistoryCleared / AutoIncrementGapsqlite_sequence recorded N insertions; fewer than N rows remain. The auto-increment counter is the shadow of everything that was ever inserted, including what was deleted.

VisitIdGap — visit IDs must be monotonically assigned. A gap of 840 IDs between row 2 and row 851 means 840 visit records were inserted and then deleted.

TimestampNonMonotonic — visit timestamps must not go backward within a session. A timestamp earlier than the preceding visit indicates record injection or manual table manipulation.

CookieTimestampAnomaly — a cookie whose creation_utc is later than its last_access_utc cannot exist naturally. The access timestamp predates the cookie's creation — the record was fabricated or the timestamps were edited.

WalPresent — a -wal file alongside the database means unflushed writes exist that are not reflected in the main file. The WAL contains the most recent state; ignoring it produces an incomplete picture.

SqliteIntegrityFailurePRAGMA integrity_check reports structural corruption. This ranges from benign (interrupted write) to deliberate (anti-forensic page manipulation).

HistoryTombstoneFound (Safari) — Safari maintains a history_tombstones table for deleted history items. Tombstones are direct evidence that history was deleted, with the deletion timestamp preserved in the schema.

DownloadFileMissing — a download record exists with a local target path, but the file is absent. The download completed; the file was removed.


Full Triage

# Discover all browser profiles under the user's home directory,
# parse every artifact, run integrity checks, and carve free pages
br4n6 triage --home /mnt/evidence/Users/jsmith --format jsonl > report.jsonl

The triage report includes:

  • All parsed browser events across Chromium, Firefox, and Safari
  • Integrity indicators from every database found
  • Carved records from SQLite free pages and WAL files
  • A manifest of discovered profiles (browser, name, path, container attribution)
  • Generation timestamp for chain-of-custody documentation

Interpretation

--interpret adds a human-readable interpretation to each event, decoding the artifacts that carry hidden structure. The interpretation engine is a clean-room reimplementation of the Hindsight interpretation plugins:

  • Google searches — extracts the query and search options from google.*/search URLs (Searched for "how to wipe a disk").
  • Query strings — decodes any URL's parameters into key: value pairs.
  • Google Analytics cookies__utma / __utmb / __utmc / __utmv / __utmz / _ga (visitor IDs, first/last visit times, campaign sources).
  • Tracking / infrastructure cookies — F5 BIG-IP BIGipServer* (decodes the backend IP:port), Quantcast __qca, and a generic embedded-timestamp scan.

Timestamps are inferred by magnitude (Unix seconds/millis/micros or WebKit), matching the ground truth without the caller declaring units. Cookie interpretation runs where a plaintext value is available (Firefox); Chrome cookie values stay encrypted and are never surfaced.

br4n6 export /mnt/evidence/Users/jsmith --interpret --format jsonl \
  | jq 'select(.interpretation | test("Searched for"))'

Correlated Export

br4n6 export collects a single correlated timeline from a profile or home directory and writes it in the format an analyst wants:

# XLSX workbook (one Timeline sheet), timestamps in the examiner's timezone
br4n6 export /mnt/evidence/Users/jsmith \
  --format xlsx -o timeline.xlsx --timezone America/New_York --interpret

# SQLite database with a single `timeline` table for ad-hoc SQL
br4n6 export /mnt/evidence/Users/jsmith --format sqlite -o timeline.sqlite

Formats: xlsx, sqlite (both require -o FILE), and streaming jsonl / csv / text. --timezone accepts any IANA name for human-facing timestamps.


Output Schema

All commands share the same BrowserEvent envelope:

{
  "timestamp_ns": 1700000000000000000,
  "browser": "Chromium",
  "artifact": "History",
  "source": "/path/to/History",
  "description": "https://example.com — Example Domain",
  "attrs": {
    "url": "https://example.com",
    "title": "Example Domain",
    "visit_count": 3
  }
}

timestamp_ns is always Unix nanoseconds. artifact is the artifact kind (History, Cookies, Downloads, Bookmarks, Autofill, LoginData, Extensions, Cache, Session, Preferences, LocalStorage, Integrity, Carved, Memory). Web-storage events use LocalStorage with a storage_type attr distinguishing Local Storage, Session Storage, and IndexedDB.


Crate Architecture

The workspace is layered — each crate has a single responsibility:

forensicnomicon              format constants, epoch offsets, SQLite magic,
                             artifact + embedded-Chromium container catalog
      |
browser-forensic-core        BrowserEvent, BrowserFamily, ArtifactKind, timestamp conversions
      |
  ┌───┴───────────────────────────────────────────────────┐
  │                                                        │
browser-forensic-chrome      Chromium / Firefox / Safari   browser-forensic-discovery
browser-forensic-firefox     artifact parsers              profile discovery + embedded-
browser-forensic-safari                                    Chromium container sweep
  │
  ├── browser-forensic-storage    Local / Session Storage, IndexedDB (reuses leveldb-forensic)
  ├── browser-forensic-integrity  history clearing, visit-ID gaps, WAL detection, timestamp anomalies
  ├── browser-forensic-carve      SQLite free-page + WAL recovery (delegates to sqlite-forensic)
  ├── browser-forensic-interpret  search-term / tracking-cookie / query-string interpretation
  └── browser-forensic-memory     byte-pattern URL/cookie scanning
      |
browser-forensic-triage      TriageReport orchestration — wires all crates into one report
      |
browser-forensic-cli         `br4n6` — dual-mode binary: scriptable CLI + interactive TUI
browser-forensic-mcp         `browser-forensic-mcp` — history/state MCP server for AI agents
                             (PII-redacted; never reads cookies, passwords, or autofill)

Each library crate is independently usable in your own Rust tooling. browser-forensic-integrity, browser-forensic-carve, and browser-forensic-memory accept Path or &[u8] — they are medium-agnostic and have no dependency on any image format or memory-dump layer.

Crate Description
browser-forensic-core Domain types, timestamp conversions, ForensicMeta lookups
browser-forensic-chrome Chromium history, cookies, downloads, bookmarks, autofill, login data, extensions, cache, session, Local State, preferences
browser-forensic-firefox Firefox history, cookies, downloads, bookmarks, autofill, extensions, session (mozLz4), login data, preferences
browser-forensic-safari Safari history, cookies, downloads, bookmarks, extensions, TopSites
browser-forensic-discovery Browser profile discovery plus embedded-Chromium container sweep (macOS, Linux, Windows)
browser-forensic-storage Web storage — Local / Session Storage and IndexedDB (Chromium via leveldb-forensic, Firefox via SQLite)
browser-forensic-integrity History clearing, visit-ID gaps, timestamp anomalies, WAL presence, tombstones
browser-forensic-carve SQLite free-page carving and WAL frame recovery (via sqlite-forensic)
browser-forensic-interpret Google-search, tracking-cookie, and query-string interpretation
browser-forensic-memory Byte-pattern URL/cookie scanning for memory forensics
browser-forensic-triage triage_profile() + triage()TriageReport
browser-forensic-cli br4n6 — scriptable text/JSONL/CSV CLI plus an interactive vi-keyed terminal viewer (br4n6 tui)
browser-forensic-mcp browser-forensic-mcp — an MCP server exposing history/state to AI agents, with PII redaction and no secret readers

Using as a Library

[dependencies]
browser-forensic-chrome    = { git = "https://github.com/SecurityRonin/browser-forensic" }
browser-forensic-integrity = { git = "https://github.com/SecurityRonin/browser-forensic" }
browser-forensic-carve     = { git = "https://github.com/SecurityRonin/browser-forensic" }
use browser_forensic_chrome::parse_history;
use browser_forensic_integrity::{check_history_integrity, IntegrityIndicator};
use browser_forensic_core::BrowserFamily;

let events = parse_history(path)?;
let indicators = check_history_integrity(path, BrowserFamily::Chromium)?;

for ind in &indicators {
    match ind {
        IntegrityIndicator::HistoryCleared { detected_at_ns, .. } => {
            eprintln!("History was cleared at {detected_at_ns}");
        }
        IntegrityIndicator::VisitIdGap { expected_id, found_id, .. } => {
            eprintln!("Visit ID gap: expected {expected_id}, found {found_id}");
        }
        _ => {}
    }
}

Trust but verify

Browser databases are evidence. This suite is built to read them without altering them and without trusting their contents:

  • Read-only on evidence — SQLite databases are opened read-only; the tool never writes back to the artifact, so timestamps and free pages stay intact for re-examination.
  • forbid(unsafe) — the entire workspace denies unsafe code at compile time. Malformed, attacker-controlled artifacts cannot reach a raw pointer path.
  • Panic-free parsersclippy::unwrap_used / expect_used are denied in production code; length and offset fields from the artifact are bounds-checked before use.
  • Fuzzedcargo-fuzz targets cover the Firefox session, SQLite history, carving, integrity, and forensic-catalog paths; every target is built and smoke-run in CI (fuzz.yml).
  • Coverage gate — CI enforces a line-coverage floor via cargo llvm-cov; the uncovered remainder is the irreducible imperative shell of the binaries.
  • CI on Linux, macOS, and Windows — every push runs cargo fmt --check, cargo clippy -D warnings, build, and the full test suite on all three platforms.
  • Supply-chain gatecargo-deny checks licenses, RustSec advisories, and banned dependencies on every push (deny.toml).

RapidTriage Ecosystem

browser-forensic is one parser library in the RapidTriage DFIR toolkit:

Crate Artifact family
browser-forensic Chrome / Firefox / Safari + embedded Chromium
winevt-forensic Windows Event Logs (EVTX)
srum-forensic Windows SRUM / ESE
memory-forensic Process memory, page tables
forensicnomicon Artifact catalog, format constants

Privacy Policy · Terms of Service · © 2026 Security Ronin Ltd

About

Parse Chrome/Firefox/Safari and embedded-Chromium app artifacts — history, cookies, web storage, integrity/tampering, free-page carving, container discovery — into one JSON timeline. Single static Rust binary, no runtime deps.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages