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

@@ -282,21 +282,30 @@ def resolve_signup_url(draft: SignupDraft) -> str:
def load_draft() -> SignupDraft:
from . import secrets_store as _ss
p = draft_path()
if not p.is_file():
return SignupDraft()
try:
raw = json.loads(p.read_text(encoding="utf-8"))
return SignupDraft(**{k: raw.get(k, "") for k in SignupDraft.__dataclass_fields__})
kwargs = {k: raw.get(k, "") for k in SignupDraft.__dataclass_fields__}
if kwargs.get("password"):
kwargs["password"] = _ss.decrypt(kwargs["password"])
return SignupDraft(**kwargs)
except (OSError, json.JSONDecodeError, TypeError):
return SignupDraft()
def save_draft(draft: SignupDraft) -> None:
draft_path().write_text(json.dumps(asdict(draft), indent=2), encoding="utf-8")
from . import secrets_store as _ss
d = asdict(draft)
if d.get("password"):
d["password"] = _ss.encrypt(d["password"])
draft_path().write_text(json.dumps(d, indent=2), encoding="utf-8")
def load_accounts() -> list[AccountRecord]:
from . import secrets_store as _ss
p = accounts_path()
if not p.is_file():
return []
@@ -312,6 +321,9 @@ def load_accounts() -> list[AccountRecord]:
kwargs = {k: item.get(k, "") for k in fields}
if not kwargs.get("id"):
kwargs["id"] = datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S%f")
# Transparent DPAPI decrypt; plaintext passes through.
if kwargs.get("password"):
kwargs["password"] = _ss.decrypt(kwargs["password"])
out.append(AccountRecord(**kwargs))
return out
except (OSError, json.JSONDecodeError, TypeError):
@@ -319,8 +331,17 @@ def load_accounts() -> list[AccountRecord]:
def save_accounts(rows: list[AccountRecord]) -> None:
from . import secrets_store as _ss
serialized = []
for r in rows:
d = asdict(r)
# Encrypt sensitive fields at rest using Windows DPAPI when available.
# Legacy plaintext entries are migrated transparently on first save.
if d.get("password"):
d["password"] = _ss.encrypt(d["password"])
serialized.append(d)
accounts_path().write_text(
json.dumps([asdict(r) for r in rows], indent=2),
json.dumps(serialized, indent=2),
encoding="utf-8",
)