fix(webrtc): ship the validated proxy realness config + CI guards

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.
This commit is contained in:
feder-cr
2026-06-10 14:30:16 +02:00
parent 584ad97179
commit e524695088
10 changed files with 249 additions and 51 deletions
+37
View File
@@ -214,6 +214,43 @@ def test_mdns_host_is_invisible_to_creep_resolver():
assert creep_get_ipaddress("v=0\r\nc=IN IP4 0.0.0.0\r\n" f"a={HOST_MDNS}\r\n") is None
# ──────────────────────────────────────────────────────────────────────────
# SHIPPED-BASELINE guard — the cheap unit test that would have caught the
# 2026-06-10 gap (baseline obfuscate=False, dead disableIPv6, orphan prefs).
# These lock the shipped wrapper config to the manually-validated one so a
# future edit / merge can't silently un-ship it. Run in tests.yml.
# ──────────────────────────────────────────────────────────────────────────
from invisible_playwright._fpforge import generate_profile # noqa: E402
from invisible_playwright.prefs import translate_profile_to_prefs # noqa: E402
@pytest.mark.unit
def test_shipped_webrtc_baseline_is_the_validated_config():
prefs = translate_profile_to_prefs(generate_profile(seed=42))
# host candidate must be mDNS .local like vanilla Firefox (manually
# validated on BrowserLeaks/CreepJS through a residential proxy) — not a
# raw LAN IP.
assert prefs["media.peerconnection.ice.obfuscate_host_addresses"] is True
# IPv6 dropped via OUR live filter pref; the native pref is dead on FF150
# and must not be relied upon (or re-introduced as if it worked).
assert prefs["zoom.stealth.webrtc.disable_ipv6"] is True
assert "media.peerconnection.ice.disableIPv6" not in prefs
# peerconnection stays ON (a disabled WebRTC is itself a tell).
assert prefs["media.peerconnection.enabled"] is True
@pytest.mark.unit
def test_no_orphan_prefs_in_baseline():
"""zoom.stealth.timezone / zoom.stealth.seed are read by NO C++ — they must
not be written (juggler.timezone.override + zoom.stealth.fpp.hw_seed are the
real ones). Guards against re-introducing a pref the binary ignores."""
prefs = translate_profile_to_prefs(generate_profile(seed=42), timezone="America/Chicago")
assert "zoom.stealth.timezone" not in prefs
assert "zoom.stealth.seed" not in prefs
assert prefs["juggler.timezone.override"] == "America/Chicago"
assert "zoom.stealth.fpp.hw_seed" in prefs
# ──────────────────────────────────────────────────────────────────────────
# Fake-proxy infrastructure for e2e: a tiny TCP-only SOCKS5 server.
# ──────────────────────────────────────────────────────────────────────────