From b98c4ae116f339104f54047044ce1cab613131b6 Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Sat, 2 May 2026 20:15:09 +0200 Subject: [PATCH] fix: validate key spec before saving/loading from remotes.json A previous bug (fixed in fcd2e8b) caused str(AgentKey(...)) to be saved as the key spec instead of the plain string "agent". This made _load_private_key() return None, sending messages unsigned. - _is_valid_key_spec() guards save_remote_key() against persisting serialized objects or other non-spec values - key_for_remote() rejects already-persisted corrupt specs so fallback key loading still works Co-Authored-By: Claude Sonnet 4.6 --- browser_cli/client.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/browser_cli/client.py b/browser_cli/client.py index 906da10..634c259 100644 --- a/browser_cli/client.py +++ b/browser_cli/client.py @@ -86,10 +86,17 @@ def token_for_remote(endpoint: str | None) -> str | None: return str(token) if token else None +def _is_valid_key_spec(s: str) -> bool: + """Return True if s looks like a usable key spec: 'agent', 'agent:', or a file path.""" + return s == "agent" or s.startswith("agent:") or (not s.startswith("<") and "/" in s or Path(s).suffix in {".pem", ".key"}) + + def save_remote_key(endpoint: str, key_spec: str) -> None: """Persist the key spec (e.g. 'agent' or a file path) for a remote endpoint.""" if not endpoint or not key_spec: return + if not _is_valid_key_spec(key_spec): + return # refuse to save serialized objects or other garbage remotes = _load_remotes() current = remotes.get(endpoint, {}) current["key"] = key_spec @@ -105,7 +112,13 @@ def key_for_remote(endpoint: str | None) -> str | None: return None cfg = _load_remotes().get(endpoint) or {} key = cfg.get("key") - return str(key) if key else None + if not key: + return None + key_str = str(key) + # reject corrupted values (e.g. str(AgentKey(...)) saved by an older bug) + if not _is_valid_key_spec(key_str): + return None + return key_str def _remote_display_name(endpoint: str, profile_name: str, display_name: str) -> str: