fix(git): validate API-supplied repository URLs before running git
What does this MR do and why?
glab passed repository URLs from API responses (ssh_url_to_repo, http_url_to_repo) straight to git clone, git fetch, and git remote add. A compromised or intercepted instance could return a value that git reads as an option or a remote-helper transport. glab now validates these URLs before using them and passes -- before the URL to git.
Two other API fields get the same treatment: repo clone validates path_with_namespace and path before building local directories from them, and mr checkout validates source_branch before using it as a git argument.
For users: no change with any value a GitLab instance generates. A malformed value now fails with invalid git remote URL, invalid project path, or invalid branch name before git runs.
Details
Validation (git.ValidateRemoteURL, called from glrepo.RemoteURL and glrepo.WikiRemoteURL, which now return an error):
- Accepts
ssh://,git+ssh://,git://,http://,https://(case-insensitive), and scp-like[user@]host:path/[user@host]:path. These cover every form GitLab builds inconfig/settings.rb(build_gitlab_shell_ssh_path_prefix): customssh_user, emptyssh_user, IPv6 hosts, and non-22 ports. - Rejects values starting with
-,<transport>::<address>remote-helper URLs,file://and local paths, and anything containing whitespace or control characters. IsValidURLis unchanged: it decides whether user input is a URL or a project path, and that behavior stays.
-- at every sink: RunClone (after user-supplied -- <gitflags>, so glab repo clone x -- --depth 1 still works), AddRemote, AddUpstreamRemote, project create's remote add origin, and both fetch calls in mr checkout.
Callers updated: mr checkout (fails before fetch and before writing branch.<name>.remote), mr create, repo clone (project, wiki, fork upstream), repo create, repo fork (4 sites), repo remote add.
Project paths (repo clone): path_with_namespace (--preserve-namespace) and path (group clone with --dir, fork upstream directory) must be relative with no empty, ., or .. segment, no backslash, and no leading -. --dir itself is not validated.
Branch name (mr checkout): the resolved branch (from --branch or source_branch) must not be empty, start with -, or contain whitespace or control characters. -- can't protect this one because git checkout -- <x> treats x as a path. git validates the remaining ref-name rules itself.
Tests: table test for the validator; RemoteURL/WikiRemoteURL error paths; command-level tests for mr checkout, repo clone, and repo remote add asserting an error and no git invocation when the API returns an option-like URL, a traversing project path, or an option-like branch name. Integration fixtures for mr checkout now serve the bare origin over HTTP. Fixtures that previously had empty clone URLs now carry realistic ones.
Closes #8524