Skip to content
neatlabs-aiPublic

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

REVENANT

CI License: MIT Python Status

Favicon supercookie & persistent-tracking auditor. Point it at a domain. It loads the site twice through one warm profile, diffs the two network traces, and reports — in an Admiralty-rated intelligence format — whether the site is using cache state to build an identifier that survives cookie clearing, incognito, VPNs and ad blockers.

A revenant is something you deleted that comes back. That's the whole threat class: trackers that live in browser state your "clear history" button doesn't touch.

Project status — 0.1.0 (alpha). The detection engine is unit-tested against synthetic traces; live calibration against real sites is in progress. Treat findings as leads weighted by their Admiralty rating, not verdicts.


Why this exists

In 2021 Jonas Strehle's supercookie PoC (built on University of Illinois, Chicago research) showed favicons could carry a near-permanent ID. Modern Chromium and Safari largely closed the specific vector with cache partitioning — the favicon cache is now keyed to the top-level site, so one site can't read favicons another set. But:

  • Not every browser/version is partitioned, and embedded/mobile webviews lag.
  • The favicon trick is one member of a family — ETag/validator IDs, redirect bounce tracking, HSTS pins, service-worker/IndexedDB persistence — that is very much alive.

REVENANT detects the whole family, with the favicon supercookie as the headline signature.

What it detects

Vector Code Method strength
Favicon-cache supercookie favicon-supercookie full mechanical signature (A)
ETag / cache-validator tracking etag-supercookie issue + revisit echo (A/B)
Redirect bounce tracking bounce-tracking cross-site nav hops (B/C)
Persistent client storage (SW/IDB/LS) persistent-storage direct storage read (B/D)
HSTS pin supercookie hsts-supercookie heuristic shape only (D)

How the favicon detection works

On a fresh profile the auditor watches for the mechanical signature:

  1. a chain of same-site redirects (301/302/303/307/308) on initial load, with no user interaction;
  2. a distinct favicon probe (separate origin/path = separate cache slot) interleaved with each hop;
  3. chain length in the log2(population) band — ~16–32 hops = 65k–4B IDs;
  4. the whole thing as a tight automated burst (~2s for 32 hops).

Then it reloads the same warm profile and looks for the confirmer: the favicon probes are now served from cache / suppressed while the redirect scaffold persists. That suppression is the proof the cache is being read as a state channel, not used for ordinary caching.

Admiralty rating

Every finding carries a NATO Admiralty Code, e.g. A1:

  • Letter — reliability of the detection method (A best … F unknown). Full signature observed = A.
  • Digit — corroboration across independent signals (1 confirmed … 6 unknown). All four favicon signals firing = 1.

A 0–100 composite confidence drives the severity band (informational → critical).

Install

git clone https://github.com/<you>/revenant && cd revenant
pip install -e ".[web]"          # engine + CLI + web UI
playwright install chromium      # browser binary (one-time, for live capture)

The detection engine itself has no runtime deps — only live capture needs Playwright and only the dashboard needs Flask. analyze (saved traces) runs anywhere. After install the revenant command is on your PATH.

Web UI — mission control

A local command-center dashboard wraps the engine: fire an audit from a URL bar, watch the two-pass capture run live (radar sweep, per-pass request counters, detectors lighting up), then get an interactive report with the redirect chain rendered as a visual — toggle FRESH / REVISIT to see the favicon suppression that proves the cache is a read channel.

pip install flask
python -m webapp.app                 # http://127.0.0.1:7777
REVENANT_PORT=8080 python -m webapp.app

Features: live SSE capture progress · case history (SQLite) · interactive findings with Admiralty chips and animated confidence bars · the chain visualization · one-click export to standalone HTML dossier or JSON · drag-drop a --save-trace file onto the page to analyze it with no browser capture.

Routes: GET / dashboard · POST /api/audit → live capture (SSE at /api/audit/<job>/stream) · POST /api/analyze (upload trace) · GET /api/reports[/id] · GET /report/<id>.html (dossier).

Preview without installing anything: open revenant_ui_preview.html — a self-contained snapshot of the real interface (sample data baked in) so you can click through findings and the chain viz offline.

CLI

# capture a live site and assess it
python -m revenant audit https://suspicious.example \
    --html report.html --json report.json --save-trace trace.json

# re-assess a saved trace later, no browser needed
python -m revenant analyze trace.json --html report.html

# pick an engine / give a slow site more time / watch it run
python -m revenant audit https://site.example --engine webkit --settle 4000 --headed

Exit codes (CI-friendly): 0 clean/low · 1 medium · 2 high/critical · 3 error.

python -m revenant audit "$URL" --quiet --json out.json || echo "tracking found"

Output

  • Console — Admiralty-rated findings with evidence + recommended actions.
  • --html — a self-contained dark "dossier" you can hand to a client.
  • --json — structured findings for pipelines / WATCHCORE ingest.

Testing

python tests/test_detectors.py          # plain runner
pytest tests/                            # or pytest

Tests run entirely on synthetic traces — no network, no browser.

Limitations (read these)

  • REVENANT observes behaviour, not intent. A long same-site redirect chain with favicon fan-out is the signature; a site could in principle do this for benign reasons (rare). Treat findings as leads weighted by their Admiralty rating.
  • Absence of a finding is not proof of absence of tracking.
  • CDP cache flags (fromDiskCache) are Chromium-only; on Firefox/WebKit the suppression signal falls back to fetch-count diffing, which is noisier.
  • The eTLD+1 grouping uses a compact heuristic, not the full Public Suffix List.

Where this fits

Standalone CLI, or drop the engine in as a WATCHCORE pack: run_audit() returns a structured AuditReport and report_to_dict() gives you clean JSON for the compiler. The HTML renderer already matches the intelligence-product house style.

Contributing & governance

Issues use templates for bugs, feature/vector proposals, and — importantly for a privacy auditor — false-positive / false-negative reports.

License

MIT — see LICENSE. © 2026 Randy B. / Security 360, LLC (NEATLABS™).


Built for defensive privacy assessment. Use only against systems you are authorised to test.

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages