Verify Git plugin SHA checkouts (#34644)

## Why

Git can interpret a requested commit SHA as a branch name when the remote's
default branch has the same name. This can cause a marketplace plugin source
to materialize a different commit than the one it pinned.

## What changed

Resolve `HEAD` after checking out a SHA-pinned Git plugin source and reject the
source when the resolved commit does not exactly match the requested SHA.
Ref-name checkouts retain their existing behavior.

## Testing

Add a regression test with a default branch named after another commit's SHA
and verify that materialization rejects the mismatched checkout.

GitOrigin-RevId: c19cbd98ee6167dad7b2ee72e283b3bd30b59713
This commit is contained in:
caseysilver-oai authored and copyberry committed 2026-07-22 01:20:13 +00:00
1 parent 539c0e1100
commit 690995b7c1
2 files changed
+60 -4

No files matched your search

+15 -3
View File
@@ -1523,8 +1523,16 @@ fn clone_git_plugin_source(
/*cwd*/ None,
)?;
}
if let Some(target) = sha.or(ref_name) {
run_git(&["checkout", target], Some(destination))?;
if let Some(sha) = sha {
run_git(&["checkout", sha], Some(destination))?;
let checked_out_sha = run_git_output(&["rev-parse", "HEAD"], Some(destination))?;
if !checked_out_sha.eq_ignore_ascii_case(sha) {
return Err(format!(
"checked out Git SHA {checked_out_sha} does not match requested SHA {sha}"
));
}
} else if let Some(ref_name) = ref_name {
run_git(&["checkout", ref_name], Some(destination))?;
} else if sparse_checkout_path.is_some() {
run_git(&["checkout"], Some(destination))?;
}
@@ -1532,6 +1540,10 @@ fn clone_git_plugin_source(
}
fn run_git(args: &[&str], cwd: Option<&Path>) -> Result<(), String> {
run_git_output(args, cwd).map(drop)
}
fn run_git_output(args: &[&str], cwd: Option<&Path>) -> Result<String, String> {
let mut command = Command::new("git");
command.args(args);
command.env("GIT_TERMINAL_PROMPT", "0");
@@ -1543,7 +1555,7 @@ fn run_git(args: &[&str], cwd: Option<&Path>) -> Result<(), String> {
.output()
.map_err(|err| format!("failed to run git {}: {err}", args.join(" ")))?;
if output.status.success() {
return Ok(());
return Ok(String::from_utf8_lossy(&output.stdout).trim().to_string());
}
Err(format!(