fix(ssh): reject option-injection destinations (C1)

A remote destination's user@host token is passed to ssh in option
position, so a host beginning with '-' (e.g. -oProxyCommand=...) was
parsed by ssh as an option, allowing arbitrary command execution.

- config_parse_ssh_dest now validates the user@host prefix and returns
  -1 (with a clear logged error) for an empty host or a user/host that
  starts with '-'; config_parse_transport_dest propagates the failure.
- transport_ssh.c's parse_remote_dest applies the same validation as
  defense-in-depth, and ssh_build_client_argv inserts a '--'
  end-of-options marker before the destination token.
- Unit tests cover -oProxyCommand=... / -prefixed hosts / empty host
  rejection and the argv shape.
This commit is contained in:
2026-09-14 16:08:56 +02:00
parent df887c73b1
commit f75a69f96a
5 changed files with 104 additions and 20 deletions
+4 -1
View File
@@ -851,7 +851,10 @@ bool config_send(int file_descriptor, const Config* config);
bool config_send_wire_block(int file_descriptor, const Config* config);
Config* config_receive(int file_descriptor);
bool config_is_remote_dest(const char* s);
void config_parse_ssh_dest(Config* config);
/* Parse a single-colon host:path SSH destination (0 = not an SSH destination or
* parsed successfully, -1 = rejected, e.g. a user@host beginning with '-'; the
* reason is logged). */
int config_parse_ssh_dest(Config* config);
/* A ConfigValidateFunc may return this sentinel to tell
* config_receive_with_validate that the callback ALREADY sent a terminal status