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
Part of #275
Part of the OpenSSH drop-in compatibility epic.
Problem
ProxyCommandis parsed atsrc/ssh/ssh_config/parser/options/proxy.rs:39, security-validated insrc/ssh/ssh_config/security/string_validation.rs, merged by the resolver atsrc/ssh/ssh_config/resolver.rs:111, and documented as supported in bothREADME.md(lines 1012-1022) anddocs/man/bssh.1(line 1053). It is never executed. The identifierproxy_commanddoes not appear anywhere outsidesrc/ssh/ssh_config/, and unlikeProxyJump, which reaches the jump chain throughSshConfig::get_proxy_jumpatsrc/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.regressdescribes the suite as "network or proxycommand based tests";test-exec.sh:888generates$OBJ/ssh_proxycarrying aproxycommandline, and the majority of connection-level tests run over that config rather than over TCP.proxy-connectfails today withssh proxyconnect comp=no failed.Scope
ProxyCommandas a child process and use its stdin and stdout as the transport for the SSH session, instead of opening a socket to the target.%h,%p,%r,%nand related token expansions before execution, and run the command through a shell the way OpenSSH does, since real-world values contain pipes and quoting.ProxyCommand noneas an explicit disable.ProxyCommand,ProxyJumpand-Jto match OpenSSH, where the most recently obtained value wins and-Jon the command line overrides both.ProxyUseFdpass, whichREADME.mdalso documents, or reject it as unimplemented. It must not stay in the silently-parsed state that caused this issue.Acceptance criteria
ProxyCommandroutes the session through the child process, verified by a test that would fail if the connection were direct.ProxyCommandandProxyJumpprecedence matches OpenSSH.proxy-connectpasses in the harness, and the connection-level tests that run over$OBJ/ssh_proxybecome reachable.Part of #275