fix(remote): validate remote URL, name and refspecs

Call validate_remote_url, validate_ref_name, and validate_refspec before
passing user input to git subprocess in update_remote_mirror, fetch_remote,
and create_repository_from_url.
This commit is contained in:
zhenyi
2026-06-10 18:31:50 +08:00
parent 1c22700769
commit 0665772079
+14 -5
View File
@@ -8,13 +8,18 @@ impl GitBare {
&self, &self,
request: UpdateRemoteMirrorRequest, request: UpdateRemoteMirrorRequest,
) -> GitResult<UpdateRemoteMirrorResponse> { ) -> GitResult<UpdateRemoteMirrorResponse> {
crate::sanitize::validate_remote_url(&request.remote_url)?;
let remote_name = if request.remote_name.is_empty() { let remote_name = if request.remote_name.is_empty() {
"origin" "origin"
} else { } else {
&request.remote_name &request.remote_name
}; };
crate::sanitize::validate_ref_name(remote_name)?;
for rs in &request.refspecs {
crate::sanitize::validate_refspec(rs)?;
}
// Add or update remote
let remote_check = std::process::Command::new("git") let remote_check = std::process::Command::new("git")
.args([ .args([
"--git-dir", "--git-dir",
@@ -26,7 +31,6 @@ impl GitBare {
.output(); .output();
if remote_check.is_err() || !remote_check.unwrap().status.success() { if remote_check.is_err() || !remote_check.unwrap().status.success() {
// Add new remote
std::process::Command::new("git") std::process::Command::new("git")
.args([ .args([
"--git-dir", "--git-dir",
@@ -42,7 +46,6 @@ impl GitBare {
stderr: e.to_string(), stderr: e.to_string(),
})?; })?;
} else { } else {
// Update existing remote URL
std::process::Command::new("git") std::process::Command::new("git")
.args([ .args([
"--git-dir", "--git-dir",
@@ -59,7 +62,6 @@ impl GitBare {
})?; })?;
} }
// Fetch
let mut fetch_args = vec![ let mut fetch_args = vec![
"--git-dir".to_string(), "--git-dir".to_string(),
self.bare_dir.to_string_lossy().into_owned(), self.bare_dir.to_string_lossy().into_owned(),
@@ -129,13 +131,18 @@ impl GitBare {
/// Fetch from a remote URL without mirroring. /// Fetch from a remote URL without mirroring.
pub fn fetch_remote(&self, request: FetchRemoteRequest) -> GitResult<FetchRemoteResponse> { pub fn fetch_remote(&self, request: FetchRemoteRequest) -> GitResult<FetchRemoteResponse> {
crate::sanitize::validate_remote_url(&request.remote_url)?;
let remote_name = if request.remote_name.is_empty() { let remote_name = if request.remote_name.is_empty() {
"origin" "origin"
} else { } else {
&request.remote_name &request.remote_name
}; };
crate::sanitize::validate_ref_name(remote_name)?;
for rs in &request.refspecs {
crate::sanitize::validate_refspec(rs)?;
}
// Ensure remote exists
let exists = std::process::Command::new("git") let exists = std::process::Command::new("git")
.args([ .args([
"--git-dir", "--git-dir",
@@ -213,6 +220,8 @@ impl GitBare {
/// Clone a repository from a remote URL (bare + mirror). /// Clone a repository from a remote URL (bare + mirror).
pub fn create_repository_from_url(&self, remote_url: &str, mirror: bool) -> GitResult<()> { pub fn create_repository_from_url(&self, remote_url: &str, mirror: bool) -> GitResult<()> {
crate::sanitize::validate_remote_url(remote_url)?;
let mut args = vec!["clone".to_string()]; let mut args = vec!["clone".to_string()];
args.push("--bare".to_string()); args.push("--bare".to_string());
if mirror { if mirror {