Skip to content

Commit 7896c36

Browse files
committed
fix: Detect ambiguous usernames, maybe in all dangerous cases
This makes all the unit tests pass, as well as the journey tests that run locally. My guess is that the journey tests that run only on CI may pass as well. It also passes manual testing of specific cases of concern, by running `cargo install --path .` and then attempting the commands: gix clone 'ssh://[email protected]/abc' gix clone -- '[email protected]:abc/def' Previously, these passed -F... option arguments to ssh. Now they do not, instead refusing to run ssh and outputting: Error: Username '-Fconfigfile' could be mistaken for a command-line argument However, gix_transport::client::blocking_io::ssh::connect remains unchanged. It does not appear to use the username argument. If it should use it, then when that is added, it will also need to check for dangerous usernames. But it may be that the username is never needed just to pass `-G` for that check.
1 parent 6ba46f9 commit 7896c36

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

gix-transport/src/client/blocking_io/ssh/program_kind.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,12 @@ impl ProgramKind {
6060
}
6161
}
6262
};
63-
let host_as_ssh_arg = match url.user() {
63+
let host_maybe_with_user_as_ssh_arg = match url.user() {
6464
Some(user) => {
65+
// FIXME: See the fixme comment on Url::user_argument_safe() about its return type.
66+
if url.user_argument_safe() != Some(user) {
67+
return Err(ssh::invocation::Error::AmbiguousUserName { user: user.into() });
68+
}
6569
let host = url.host().expect("present in ssh urls");
6670
format!("{user}@{host}")
6771
}
@@ -75,8 +79,11 @@ impl ProgramKind {
7579
}
7680
};
7781

78-
// Try to force ssh to yield english messages (for parsing later)
79-
Ok(prepare.arg(host_as_ssh_arg).env("LANG", "C").env("LC_ALL", "C"))
82+
// Try to force ssh to yield English messages (for parsing later).
83+
Ok(prepare
84+
.arg(host_maybe_with_user_as_ssh_arg)
85+
.env("LANG", "C")
86+
.env("LC_ALL", "C"))
8087
}
8188

8289
/// Note that the caller has to assure that the ssh program is launched in English by setting the locale.

gix-url/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,13 @@ impl Url {
180180
///
181181
/// Use this method if the user or a portion of the URL that begins with it will be passed to a command-line application.
182182
pub fn user_argument_safe(&self) -> Option<&str> {
183+
// FIXME: A return value of None from this method, or host_argument_safe(), is ambiguous: the user (or host) is
184+
// either present but unsafe, or absent. Furthermore, in practice the value is usually needed even if unsafe,
185+
// in order to report it in an error message. In gix-transport, the ambiguity makes it easy to write a new bug
186+
// while using this interface for user_argument_safe(). In contrast, in host_argument_safe(), the ambiguity is
187+
// much less of a problem, because the host is expected to be present. Yet the host() method must still be
188+
// called when handling the None case, to include it in the error. If possible, both methods should be replaced
189+
// by methods with a richer return type (a new enum). If not, the ambiguity should be prominently documented.
183190
self.user().filter(|user| !looks_like_argument(user.as_bytes()))
184191
}
185192

0 commit comments

Comments
 (0)