Commit Graph

7 Commits

Author SHA1 Message Date
Teknium 6e41ab3460 fix(desktop): bounded auto-restart for no-mux SSH tunnel flaps instead of instant connection death (#96266)
A no-mux tunnel is a single persistent `ssh -N -L` child. On main, ANY
death of that child after readiness immediately set tunnel.alive=false,
which poisons SshConnection.isAlive() forever; upstream lifecycle probes
then treat the whole SSH connection as dead, tear down the scope, and
SIGTERM a perfectly healthy backend (~10s after HERMES_BACKEND_READY in
the #96266 logs: '[ssh] connection closed (no-mux tunnels killed)' ->
'Ignoring stale Hermes backend exit (SIGTERM)' -> 90s port-announcement
timeout, with retry/repair looping the same failure).

Now a post-readiness child death is a tunnel FLAP: the child is
restarted with a bounded budget (5 attempts, 1s delay by default,
injectable for tests) and only an exhausted budget marks the tunnel —
and thus the connection — unhealthy. Deliberate teardown (cancelForward
/ close) sets tunnel.stopping, cancels any pending restart timer, and
never restarts. Pre-readiness deaths keep failing fast with classified
stderr (auth/bind errors unchanged).

Fixes the kill chain of #96266.
2026-08-31 12:16:48 -07:00
hermes-seaeye[bot] 046a868b7f fmt(js): npm run fix on merge (#88321)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-17 10:09:48 +00:00
Teknium 6cca9f3e71 fix(desktop): validate SSH host input and redact credentials in ssh target logging
A user typed their root password into the Desktop SSH host field
(root@IP:PASSWORD form). Three failures compounded:

1. validateSshTarget() only checked for option injection (leading dash),
   control chars, and port range — commas in an IP, whitespace ("ssh "
   prefix pastes), and non-numeric ":<segment>" leftovers all dialed ssh
   with garbage and failed silently five times.
2. normalizeSshConfig() only strips a ":<segment>" when it is numeric, so
   a pasted password stayed glued to the hostname all the way into ssh
   argv and the desktop.log connect line.
3. redactSecrets() had no pattern for ssh targets, so the password landed
   verbatim in desktop.log and then in a PUBLIC debug-share paste.

Changes:
- validateSshTarget(): reject whitespace, commas, non-numeric colon
  segments (with a "never put a password in the host field" hint that
  does NOT echo the credential), and garbage hostnames; still accepts
  bare IPv6 (::1, fe80::1%eth0). Reject whitespace/@ in user.
- redactSecrets(): new pattern masks any non-numeric segment where a
  port belongs in user@host:... strings — defense in depth so future
  parse gaps can't leak credentials into logs or debug shares.
- normalizeSshConfig(): strip a pasted leading "ssh " prefix.
- Tests for all three, including the exact incident shapes.
2026-08-17 01:54:41 -07:00
addel c76b7e6343 fix(desktop): harden plugin route lifecycle 2026-08-16 16:26:50 -07:00
yoniebans faa3bce6dc style(desktop): satisfy merged eslint/prettier config
The SSH modules predate the stricter lint config that landed on main (curly, no-empty, perfectionist sorting, prettier). Mechanical lint:fix + fmt pass, empty catch blocks filled with the codebase's void-0 convention, and inline no-control-regex disables on the three deliberate control-char patterns (same pattern as lib/ansi.ts).
2026-07-20 23:01:49 +02:00
yoniebans 45acb62c6d feat(desktop): route Desktop SSH to the Windows lifecycle
Detect the remote platform on connect and Test SSH: uname first (Linux/Darwin
keep the POSIX lifecycle), else an encoded-PowerShell probe that routes a
Windows host through connectWindowsRemote. The Windows lifecycle mirrors the
POSIX one — probe, one-shot token upload, spawn, readiness scrape, tunnel,
reuse-by-exact-ownership, and teardown — over a PowerShell helper dialect.

Preserve a backend on indeterminate process state (never destroy on unknowns);
a thrown terminate aborts before remove-lock so a live backend is never
orphaned. Interactive terminals on a Windows backend open PowerShell in the
requested cwd instead of a POSIX login shell.
2026-07-20 17:19:22 +02:00
yoniebans a340d0adc5 feat(desktop): add isolated SSH transport primitives
Add OpenSSH config discovery, scoped ControlMaster/no-mux transport, durable installation ownership, serialized bootstrap coordination, and transactional remote backend lifecycle with focused Vitest coverage.
2026-07-16 14:43:14 +02:00