Skip to content

fix(ssh_config): execute ProxyCommand instead of parsing and discarding it #280

Description

@inureyes

Part of the OpenSSH drop-in compatibility epic.

Problem

ProxyCommand is parsed at src/ssh/ssh_config/parser/options/proxy.rs:39, security-validated in src/ssh/ssh_config/security/string_validation.rs, merged by the resolver at src/ssh/ssh_config/resolver.rs:111, and documented as supported in both README.md (lines 1012-1022) and docs/man/bssh.1 (line 1053). It is never executed. The identifier proxy_command does not appear anywhere outside src/ssh/ssh_config/, and unlike ProxyJump, which reaches the jump chain through SshConfig::get_proxy_jump at src/app/initialization.rs:374, there is no accessor for it at all.

The user-visible consequence is a silent security failure: a configuration that says traffic must traverse a bastion or a SOCKS relay connects directly to the target instead, and nothing warns. Documentation that promises the feature makes this worse, because an operator has no reason to check.

It is also the largest single blocker for the regression suite. README.regress describes the suite as "network or proxycommand based tests"; test-exec.sh:888 generates $OBJ/ssh_proxy carrying a proxycommand line, and the majority of connection-level tests run over that config rather than over TCP. proxy-connect fails today with ssh proxyconnect comp=no failed.

Scope

  • Execute the resolved ProxyCommand as a child process and use its stdin and stdout as the transport for the SSH session, instead of opening a socket to the target.
  • Apply the %h, %p, %r, %n and related token expansions before execution, and run the command through a shell the way OpenSSH does, since real-world values contain pipes and quoting.
  • Honor ProxyCommand none as an explicit disable.
  • Define the precedence between ProxyCommand, ProxyJump and -J to match OpenSSH, where the most recently obtained value wins and -J on the command line overrides both.
  • Propagate the child's exit and its stderr into bssh's diagnostics so a failing proxy is reported as such rather than as a generic connection error.
  • Wire ProxyUseFdpass, which README.md also documents, or reject it as unimplemented. It must not stay in the silently-parsed state that caused this issue.

Acceptance criteria

  • A config with ProxyCommand routes the session through the child process, verified by a test that would fail if the connection were direct.
  • Token expansion is covered by tests, including a command containing a pipe.
  • A failing or missing proxy command produces a diagnostic naming the command and its exit status.
  • ProxyCommand and ProxyJump precedence matches OpenSSH.
  • The regress test proxy-connect passes in the harness, and the connection-level tests that run over $OBJ/ssh_proxy become reachable.

Part of #275

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions