From 029b6789641cc256fb1dbaed5356326453650e04 Mon Sep 17 00:00:00 2001 From: feder-cr <85809106+feder-cr@users.noreply.github.com> Date: Mon, 6 Jul 2026 03:09:35 +0200 Subject: [PATCH] fonts: stop injecting STEALTHFOX_FONTLIST/SYSTEMUI env (binary self-contained) The patched binary is always bundle-only and needs no external font config, so the wrapper no longer injects any font env in _build_env (sync + async). No external font customization channel remains. Test updated. --- src/invisible_playwright/async_api.py | 12 ++---------- src/invisible_playwright/launcher.py | 16 +++------------- tests/test_launcher_helpers.py | 14 +++++++------- 3 files changed, 12 insertions(+), 30 deletions(-) diff --git a/src/invisible_playwright/async_api.py b/src/invisible_playwright/async_api.py index 2c04938..daf64ae 100644 --- a/src/invisible_playwright/async_api.py +++ b/src/invisible_playwright/async_api.py @@ -227,16 +227,8 @@ class InvisiblePlaywright: env = _os.environ.copy() if self._timezone: env["TZ"] = _tz_env(self._timezone) - # Font allow-list + system-ui via env (read at the gfxPlatformFontList - # constructor, process start) — Playwright delivers firefox_user_prefs - # over the juggler protocol after start, too late for the font list ctor, - # so without this host fonts leak on Linux/macOS. See sync launcher. - fontlist = prefs.get("zoom.stealth.font.fontlist") - if fontlist: - env["STEALTHFOX_FONTLIST"] = fontlist - system_ui = prefs.get("zoom.stealth.font.system_ui") - if system_ui: - env["STEALTHFOX_SYSTEMUI"] = system_ui + # Fonts need NO env: the patched binary is self-contained (always + # bundle-only). No external font list / allow-list / system-ui. # WebRTC srflx override: feed nICEr's nr_stealth_bridge the proxy egress # IP (caller's explicit env var wins, else the IP auto-discovered in # __aenter__) and drop IPv6 from gathering behind a proxy. diff --git a/src/invisible_playwright/launcher.py b/src/invisible_playwright/launcher.py index 559ba2f..6a02bcb 100644 --- a/src/invisible_playwright/launcher.py +++ b/src/invisible_playwright/launcher.py @@ -382,24 +382,14 @@ class InvisiblePlaywright: a synthetic srflx candidate matching the proxy egress IP, avoiding the StaticPref IPC propagation timing issue between parent and socket processes. - ``STEALTHFOX_FONTLIST`` / ``STEALTHFOX_SYSTEMUI`` carry the font - allow-list + system-ui family for the SAME reason: the binary reads - them at the gfxPlatformFontList constructor (process start), but - Playwright delivers firefox_user_prefs over the juggler protocol - AFTER start — too late for the font list ctor. The env var is present - at start and inherited by content processes, so the allow-list is - applied on every host (without it, host fonts leak on Linux/macOS). + Fonts need NO env: the patched binary is self-contained (always + bundle-only, exposing exactly the bundled standard-Windows families; + system-ui + generics baked in C++). No external font list / allow-list. """ import os as _os env = _os.environ.copy() if self._timezone: env["TZ"] = _tz_env(self._timezone) - fontlist = prefs.get("zoom.stealth.font.fontlist") - if fontlist: - env["STEALTHFOX_FONTLIST"] = fontlist - system_ui = prefs.get("zoom.stealth.font.system_ui") - if system_ui: - env["STEALTHFOX_SYSTEMUI"] = system_ui # WebRTC srflx override: feed nICEr's nr_stealth_bridge the proxy egress # IP so the srflx candidate matches the proxy (not the real host the # UDP STUN would otherwise leak). An explicit env var set by the caller diff --git a/tests/test_launcher_helpers.py b/tests/test_launcher_helpers.py index 1847001..a018fec 100644 --- a/tests/test_launcher_helpers.py +++ b/tests/test_launcher_helpers.py @@ -207,18 +207,18 @@ def test_build_env_caller_env_override_wins(monkeypatch): @pytest.mark.unit -def test_build_env_injects_font_list_and_system_ui(): - # The binary reads these at the gfxPlatformFontList constructor (process - # start); Playwright delivers firefox_user_prefs over juggler AFTER start, so - # the env var is the only at-construction channel. Without it host fonts leak - # on Linux/macOS (the wrapper's pref-only delivery was a cross-OS gap). +def test_build_env_never_injects_font_env(): + # The patched binary is self-contained for fonts (always bundle-only; the + # exposed set IS the bundle, system-ui + generics baked in C++). The wrapper + # must NOT inject any STEALTHFOX_FONTLIST/SYSTEMUI env — even if legacy font + # prefs are passed — so there is no external font customization channel. ip = InvisiblePlaywright(seed=42) env = ip._build_env({ "zoom.stealth.font.fontlist": "arial,calibri,segoe ui", "zoom.stealth.font.system_ui": "Segoe UI", }) - assert env["STEALTHFOX_FONTLIST"] == "arial,calibri,segoe ui" - assert env["STEALTHFOX_SYSTEMUI"] == "Segoe UI" + assert "STEALTHFOX_FONTLIST" not in env + assert "STEALTHFOX_SYSTEMUI" not in env @pytest.mark.unit