fix: validate key spec before saving/loading from remotes.json
Testing / test (push) Successful in 29s

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 <noreply@anthropic.com>
This commit is contained in:
2026-05-02 20:15:09 +02:00
parent fcd2e8b87b
commit b98c4ae116
+14 -1
View File
@@ -86,10 +86,17 @@ def token_for_remote(endpoint: str | None) -> str | None:
return str(token) if token else 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:<sel>', 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: 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.""" """Persist the key spec (e.g. 'agent' or a file path) for a remote endpoint."""
if not endpoint or not key_spec: if not endpoint or not key_spec:
return return
if not _is_valid_key_spec(key_spec):
return # refuse to save serialized objects or other garbage
remotes = _load_remotes() remotes = _load_remotes()
current = remotes.get(endpoint, {}) current = remotes.get(endpoint, {})
current["key"] = key_spec current["key"] = key_spec
@@ -105,7 +112,13 @@ def key_for_remote(endpoint: str | None) -> str | None:
return None return None
cfg = _load_remotes().get(endpoint) or {} cfg = _load_remotes().get(endpoint) or {}
key = cfg.get("key") 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: def _remote_display_name(endpoint: str, profile_name: str, display_name: str) -> str: