Audit follow-up (2026-06-10), all validated before commit.
#2 WebRTC — the shipped baseline now MATCHES the manually-validated config
(behind a residential proxy: host=<uuid>.local, srflx=proxy egress, No-Leak,
gathering completes, indistinguishable from vanilla Firefox on BrowserLeaks +
CreepJS):
- prefs baseline obfuscate_host_addresses False->True; add
zoom.stealth.webrtc.disable_ipv6=True; drop the dead
media.peerconnection.ice.disableIPv6 (no-op on FF150)
- launcher auto-derives the proxy egress IP via _geo.prepare_session_geo
(one round-trip shared with the timezone resolution) and feeds nICEr via
STEALTHFOX_WEBRTC_PUBLIC_IP + STEALTHFOX_WEBRTC_DISABLE_IPV6 in _build_env
(sync + async); an explicit caller env still wins. The C++ mechanisms were
already in firefox-9 — this activates them, no rebuild.
#1 drop orphan prefs zoom.stealth.timezone + zoom.stealth.seed (read by no C++;
the live ones are juggler.timezone.override + zoom.stealth.fpp.hw_seed).
#3 release title 'rev N' instead of 'rev firefox-N'.
CI guards (unit, leak-safe — no real proxy/creds, the kind that would have
caught this gap at zero cost):
- shipped-baseline guard + no-orphan-prefs (test_webrtc_realness.py)
- egress auto-derive in _build_env (test_launcher_helpers.py)
- prepare_session_geo returns (tz, egress) (test_geo.py)
CI keeps faking 'behind a proxy' with an in-process TCP-only SOCKS5 + RFC 5737
TEST-NET IPs; real-proxy residential realness stays a LOCAL manual gate.
449 unit pass.
Refine timezone="auto" so it ALWAYS resolves (drop the "host" sentinel):
- ""/"auto" resolve from the proxy egress when a proxy is set, else from the
host own public IP (direct lookup); an explicit zone is the only opt-out.
- on failure: with a proxy raise; without a proxy fall back to the host TZ.
GeoIP DB now auto-updates against daijro/geoip-all-in-one weekly rebuild:
cache the latest, re-check after GEOIP_REFRESH_DAYS (7), prune old tags,
reuse a stale cache offline; GEOIP_MMDB_VERSION is only the cold fallback.
tests: test_geo.py (37) + test_geoip_update.py; full unit suite 429 green
plus 8 live combinations (proxy / no-proxy / explicit / failing / freshness).
A proxy in a different country paired with the host timezone is the
classic timezone_mismatch signal, so a session with a proxy and no
explicit timezone now resolves the zone automatically.
- discover the egress IP through the proxy (SOCKS via requests[socks]),
map it to an IANA zone with an offline mmdb (daijro/geoip-all-in-one,
downloaded + cached like the Firefox binary; GPL so not vendored)
- precedence: explicit zone wins; ""+proxy and "auto"+proxy resolve;
""/"auto" without a proxy stay host; "host"/"local" force host TZ
- fail-early when a proxy is set but the zone cannot be resolved, never
a silent host-TZ fallback
- deps: requests[socks], maxminddb, tzdata (zoneinfo ships no DB on Windows)
- resolve_session_timezone / ensure_geoip_mmdb exported for integrations