You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug(slm): ssh key checks crash with PermissionError when key dir unreadable — Path(SSH_KEY_PATH).exists() at 7 sites #11793
The SLM ssh helpers gate the optional -i <key> flag on Path(SSH_KEY_PATH).exists(). pathlib.Path.exists() only swallows ENOENT/ENOTDIR-class errnos — EACCES propagates, so when the key's parent directory is unreadable by the SLM process the whole call chain crashes with an unhandled PermissionError instead of degrading to the default ssh identity.
Baseline evidence (surfaced while repairing #11737 — real SyncOrchestrator under test on a box where /home/autobot/.ssh is another user's dir):
tests/services/test_sync_orchestrator_ssh.py:63: in test_build_ssh_command_port_and_target
cmd = _orchestrator()._build_ssh_command(2222, "u", "h")
services/sync_orchestrator.py:122: in _build_ssh_command
if Path(SSH_KEY_PATH).exists():
/usr/lib/python3.10/pathlib.py:1097: in stat
return self._accessor.stat(self, follow_symlinks=follow_symlinks)
E PermissionError: [Errno 13] Permission denied: '/home/autobot/.ssh/autobot_key'
In production this means a permissions misconfiguration on /home/autobot/.ssh turns every role-sync / code-distribution / node-exec ssh build into a hard 500 instead of an actionable "key not usable" degradation.
Proposed fix
Replace Path(KEY).exists() with os.access(KEY, os.R_OK) at all 7 sites: returns False for both missing AND unreadable keys (an unreadable key cannot be used by ssh anyway), never raises. os is already imported in all three modules.
This is a deliberate behavior change in security-relevant ssh plumbing, so it was NOT bundled into the #11737 test-repair PR — filing for an owner-approved fast-follow instead. The #11737 tests pin SSH_KEY_PATH to a guaranteed-absent path so they stay deterministic either way.
Owner decision (2026-07-16): one safe helper, degrade + warn — canonical _ssh_key_usable() in a shared module catching PermissionError/OSError, logging a WARNING once, returning False → fall back to default ssh identity; all 7 sites migrate to it. Implementing now.
Activity
mrveiss commentedon Jul 16, 2026
Owner decision (2026-07-16): one safe helper, degrade + warn — canonical
_ssh_key_usable()in a shared module catching PermissionError/OSError, logging a WARNING once, returning False → fall back to default ssh identity; all 7 sites migrate to it. Implementing now.fix(slm): _ssh_key_usable helper — degrade to default identity on unr…
mrveiss commentedon Jul 16, 2026
Closed — merged to Dev_new_gui. Commit: 6c51fa8 (PR #11804). Owner decision implemented: canonical services/ssh_utils.py::_ssh_key_usable — missing key quiet-False (old behavior), unreadable/OSError → False + one actionable WARNING per path → default ssh identity; 9 sites migrated (7 filed + api/nodes.py:2740 + api/code_sync.py:2550). Adjacent bug fixed: stray duplicate -o token in code_distributor ssh argv (#10277 class), regression-guarded. Evidence: tests/services 321/1/0 (8 new helper tests incl. the exact filed traceback site degrading cleanly); nodes_execution 149 passed; independent re-run identical; conftest real-loads the new module so stubs can't silently re-add -i.
github-actions commentedon Jul 16, 2026
PR #11804 (merged to
Dev_new_gui) references this issue with a close keyword.If this issue is fully resolved, close it manually. If work remains, no action is needed.