fix: sanitize settings JSON, asyncio get_running_loop, Defender exclusion, _btn cleanup, ASCII Save label

Made-with: Cursor
This commit is contained in:
Dr Jones
2026-04-15 13:39:27 -07:00
parent 1366a2f48e
commit 096c5094fb
4 changed files with 72 additions and 6 deletions

View File

@@ -75,6 +75,63 @@ class Settings:
return app_data_dir() / "settings.json"
def sanitize_settings(s: Settings) -> tuple[Settings, bool]:
"""Clamp invalid values from hand-edited JSON. Returns (settings, changed)."""
changed = False
try:
cl = int(s.chain_length)
if not (1 <= cl <= 8):
s.chain_length = max(1, min(8, cl))
changed = True
except (TypeError, ValueError):
s.chain_length = 3
changed = True
try:
p = int(s.local_port)
if not (1 <= p <= 65535):
s.local_port = max(1, min(65535, p))
changed = True
except (TypeError, ValueError):
s.local_port = 18888
changed = True
try:
if int(s.health_check_seconds) < 10:
s.health_check_seconds = 10
changed = True
except (TypeError, ValueError):
s.health_check_seconds = 180
changed = True
try:
if int(s.full_refresh_seconds) < 60:
s.full_refresh_seconds = 60
changed = True
except (TypeError, ValueError):
s.full_refresh_seconds = 1800
changed = True
try:
if int(s.validation_concurrency) < 1:
s.validation_concurrency = 1
changed = True
except (TypeError, ValueError):
s.validation_concurrency = 64
changed = True
try:
if int(s.max_candidates) < 10:
s.max_candidates = 10
changed = True
except (TypeError, ValueError):
s.max_candidates = 400
changed = True
try:
if float(s.validation_timeout_seconds) < 2.0:
s.validation_timeout_seconds = 2.0
changed = True
except (TypeError, ValueError):
s.validation_timeout_seconds = 12.0
changed = True
return s, changed
def normalize_listen_host(s: Settings) -> tuple[Settings, bool]:
"""Force loopback bind so LAN/DHCP IP changes (e.g. cloned VMs) never break the listener."""
if s.local_host == LISTEN_HOST:
@@ -103,7 +160,9 @@ def load_settings() -> Settings:
s.pinned_chain = []
if not hasattr(s, "manual_exit_proxy") or not isinstance(s.manual_exit_proxy, str):
s.manual_exit_proxy = ""
s, changed = normalize_listen_host(s)
s, ch1 = sanitize_settings(s)
s, ch2 = normalize_listen_host(s)
changed = ch1 or ch2
if changed:
try:
p.write_text(json.dumps(asdict(s), indent=2), encoding="utf-8")
@@ -113,6 +172,7 @@ def load_settings() -> Settings:
def save_settings(s: Settings) -> None:
s, _ = sanitize_settings(s)
s, _ = normalize_listen_host(s)
p = app_data_dir() / "settings.json"
p.write_text(json.dumps(asdict(s), indent=2), encoding="utf-8")