← Back to PRs

#20330: Fix SSH tunnel startup on Windows by resolving ssh from PATH

by graysurf open 2026-02-18 20:05 View on GitHub →
app: macos size: S
# Fix SSH tunnel startup on Windows by resolving ssh from PATH ## Summary This updates SSH invocation in gateway status SSH helpers to use `ssh` from PATH instead of a hardcoded Unix path. It fixes SSH tunnel/config resolution on platforms where `/usr/bin/ssh` does not exist (notably Windows), and adds regression coverage. ## Problem - Expected: `openclaw gateway status --ssh ...` should start SSH config/tunnel probing on all supported platforms where SSH is installed. - Actual: `startSshPortForward` and `resolveSshConfig` spawn `/usr/bin/ssh`, which fails on Windows with `ENOENT`. - Impact: `gateway status` SSH probing/tunneling is unavailable on Windows environments. ## Reproduction 1. On Windows, run `pnpm openclaw gateway status --ssh user@host`. 2. Observe the SSH path spawn failure (`/usr/bin/ssh` not found). - Expected result: command resolves SSH via PATH and proceeds with probing/tunnel startup. - Actual result: command fails to spawn SSH due to hardcoded Unix-only path. ## Issues Found Severity: high Confidence: high Status: fixed | ID | Severity | Confidence | Area | Summary | Evidence | Status | | --- | --- | --- | --- | --- | --- | --- | | PR-20330-BUG-01 | high | high | src/infra | SSH helpers hardcode `/usr/bin/ssh`, breaking Windows SSH probing/tunnel startup | `src/infra/ssh-config.ts`, `src/infra/ssh-tunnel.ts` | fixed | ## Fix Approach - Replace hardcoded `/usr/bin/ssh` with `ssh` in: - `src/infra/ssh-tunnel.ts` - `src/infra/ssh-config.ts` - Add regression tests: - Assert `resolveSshConfig` spawns `ssh` (`src/infra/ssh-config.test.ts`) - Add `src/infra/ssh-tunnel.test.ts` to verify PATH-based SSH spawn for tunnel startup. ## Testing - `pnpm test src/infra/ssh-config.test.ts src/infra/ssh-tunnel.test.ts` (pass) - `pnpm build` (pass) - `pnpm check` (pass) - `pnpm test` (failed in this environment; unrelated pre-existing test instability around DNS-dependent `example.com` fetch tests such as `src/web/media.test.ts` and `src/agents/tools/web-fetch.*.test.ts`) ## Risk / Notes - Low risk: this only changes SSH binary resolution to rely on platform PATH. - macOS/Linux behavior remains compatible when `ssh` is present on PATH. <!-- greptile_comment --> <h3>Greptile Summary</h3> Replaces hardcoded `/usr/bin/ssh` with PATH-resolved `ssh` in `src/infra/ssh-config.ts` and `src/infra/ssh-tunnel.ts`, fixing SSH tunnel/config resolution on Windows where the Unix path doesn't exist. - `resolveSshConfig()` and `startSshPortForward()` now spawn `ssh` via PATH lookup instead of `/usr/bin/ssh` - New test file `src/infra/ssh-tunnel.test.ts` verifies PATH-based spawn for tunnel startup with proper mock TCP server simulation - Existing `ssh-config.test.ts` extended with regression assertion on the spawned command - Remaining `/usr/bin/ssh` references in the codebase are appropriately in macOS-only Swift code and documentation — no changes needed there <h3>Confidence Score: 5/5</h3> - This PR is safe to merge — minimal, targeted fix with regression tests and no behavioral change on existing platforms. - The change is a two-line fix (one per file) replacing a hardcoded Unix path with a PATH-resolved binary name. This is a well-understood, low-risk pattern. Node.js `spawn()` with a bare command name uses the system PATH, which works correctly on all platforms. The fix is backed by new and updated tests. No existing behavior is altered on macOS/Linux where `ssh` is available on PATH. - No files require special attention. <sub>Last reviewed commit: 962814f</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs