fix: audit round 2 - DPAPI secrets, pinned hop probe, gost exe hash, admin guard, PID-scoped browser tracking, emergency disengage button, build sidecar
Some checks failed
CI / Test Python 3.10 (push) Has been cancelled
CI / Test Python 3.11 (push) Has been cancelled
CI / Test Python 3.12 (push) Has been cancelled

This commit is contained in:
Dr Jones
2026-05-22 18:07:07 -07:00
parent 04d486a335
commit ad56f75e8a
12 changed files with 502 additions and 104 deletions

View File

@@ -168,7 +168,8 @@ def _main_inner() -> None:
ctk.set_default_color_theme("dark-blue")
root = ctk.CTk()
root.title("Proxy God v2")
from . import __version__ as _APP_VERSION
root.title(f"Proxy God v{_APP_VERSION}")
root.geometry("1080x860")
root.minsize(900, 720)
root.configure(fg_color=BG)
@@ -225,6 +226,7 @@ def _main_inner() -> None:
browser = BrowserSession()
browser_should_run = [False]
browser_last_launch_ts = [0.0]
browser_relaunch_count = [0]
service_running = [False]
# ── tray ─────────────────────────────────────────────────────────────────
@@ -305,6 +307,26 @@ def _main_inner() -> None:
def _start() -> None:
_save_settings()
# Hard-stop: if the kill-switch is enabled but we are not admin, the
# firewall lockdown is silently skipped — which contradicts the
# README's "fail closed" guarantee. Refuse to start in that mode.
try:
from .firewall import is_admin as _is_admin
except Exception:
_is_admin = lambda: True # noqa: E731
if svc.settings.kill_switch_enabled and not _is_admin():
from tkinter import messagebox
if messagebox.askyesno(
"Kill-switch requires Admin",
"Kill-switch is enabled in Settings but this process is not "
"running as Administrator.\n\n"
"Continuing now will start the chain WITHOUT the firewall "
"lockdown — your traffic will not 'fail closed' if the chain "
"drops.\n\n"
"Start anyway?",
):
svc.start()
return
svc.start()
start_btn = _btn(topbar, "▶ Start", _start, w=86)
@@ -1442,12 +1464,14 @@ def _main_inner() -> None:
_save_settings()
cfg = _browser_cfg()
browser_should_run[0] = True
browser_relaunch_count[0] = 0 # user-initiated launch resets the cap
if _launch_browser_with_cfg(cfg):
browser_last_launch_ts[0] = time.monotonic()
def _stop_browser() -> None:
cfg = _browser_cfg()
browser_should_run[0] = False
browser_relaunch_count[0] = 0
ok, msg = browser.stop(dispose=cfg.disposable_profile)
_log(msg)
_refresh_browser_status()
@@ -2637,6 +2661,34 @@ def _main_inner() -> None:
fg_color=ACCENT2, hover_color=ACCENT, text_color=TEXT,
).pack(side="left")
# Emergency disengage — for crashes where the kill-switch lingers and
# the operator needs internet back fast without restarting the app.
def _emergency_disengage_now() -> None:
from tkinter import messagebox
from .firewall import emergency_disengage as _ed, is_engaged as _ie
if not _ie():
messagebox.showinfo("Kill-switch", "No Proxy God firewall rules detected — nothing to disengage.")
return
if not messagebox.askyesno(
"Emergency disengage",
"Remove ALL Proxy God firewall rules and restore normal outbound traffic?\n\n"
"Use this only when the chain has dropped and the kill-switch is "
"blocking everything.",
):
return
_ed()
messagebox.showinfo("Kill-switch", "Firewall rules removed.")
_log("Emergency disengage: firewall rules removed by operator.")
ks_btn_row = ctk.CTkFrame(sec_sec, fg_color="transparent")
ks_btn_row.pack(fill="x", padx=12, pady=(0, 8))
_btn(
ks_btn_row, "⚠ Emergency disengage firewall now",
_emergency_disengage_now,
w=320, h=28,
fg_color="#7f1d1d", hover_color="#991b1b",
).pack(side="left")
def _apply_point_and_shoot() -> None:
"""Simple safe defaults: secure + low-friction launch profile."""
use_manual_var.set(True)
@@ -2921,9 +2973,18 @@ def _main_inner() -> None:
if browser_should_run[0] and not browser.is_running():
cfg = _browser_cfg()
now = time.monotonic()
max_retries = max(0, int(svc.settings.max_browser_relaunches))
if cfg.auto_relaunch and (now - browser_last_launch_ts[0]) >= 3.0:
if _launch_browser_with_cfg(cfg):
if browser_relaunch_count[0] >= max_retries:
browser_should_run[0] = False
_log(
f"Browser auto-relaunch disabled after "
f"{browser_relaunch_count[0]} attempts — fix the profile "
"or restart manually."
)
elif _launch_browser_with_cfg(cfg):
browser_last_launch_ts[0] = now
browser_relaunch_count[0] += 1
root.after(80, _pump)
# ─────────────────────────────────────────────────────────────────────────