Skip to content

Commit 6086a6a

Browse files
committed
Review Comments Addressed
1 parent e02063c commit 6086a6a

2 files changed

Lines changed: 54 additions & 1 deletion

File tree

get_git.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,36 @@ func (g *GitGetter) GetFile(dst string, u *url.URL) error {
174174
}
175175

176176
func (g *GitGetter) checkout(ctx context.Context, dst string, ref string) error {
177-
cmd := exec.CommandContext(ctx, "git", "checkout", ref, "--")
177+
resolvedRef, err := resolveCheckoutRef(ctx, dst, ref)
178+
if err != nil {
179+
return err
180+
}
181+
182+
cmd := exec.CommandContext(ctx, "git", "checkout", resolvedRef)
178183
cmd.Dir = dst
179184
return getRunCommand(cmd)
180185
}
181186

187+
func resolveCheckoutRef(ctx context.Context, dst, ref string) (string, error) {
188+
candidates := []string{
189+
ref,
190+
"refs/remotes/origin/" + ref,
191+
"refs/tags/" + ref,
192+
}
193+
194+
for _, candidate := range candidates {
195+
cmd := exec.CommandContext(ctx, "git", "rev-parse", "--verify", "--quiet", "--end-of-options", candidate+"^{commit}")
196+
cmd.Dir = dst
197+
198+
resolvedRef, err := cmd.Output()
199+
if err == nil {
200+
return strings.TrimSpace(string(resolvedRef)), nil
201+
}
202+
}
203+
204+
return "", fmt.Errorf("invalid ref: %q", ref)
205+
}
206+
182207
// gitCommitIDRegex is a pattern intended to match strings that seem
183208
// "likely to be" git commit IDs, rather than named refs. This cannot be
184209
// an exact decision because it's valid to name a branch or tag after a series

get_git_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,34 @@ func TestGitGetter_tag(t *testing.T) {
432432
}
433433
}
434434

435+
func TestGitGetter_checkoutRefOptionInjectionRejected(t *testing.T) {
436+
if !testHasGit {
437+
t.Skip("git not found, skipping")
438+
}
439+
440+
g := new(GitGetter)
441+
repo := testGitRepo(t, "empty-repo")
442+
repo.git("config", "commit.gpgsign", "false")
443+
repo.commitFile("safe.txt", "safe")
444+
445+
secretPath := filepath.Join(t.TempDir(), "secret.txt")
446+
secretLine := "THIS_IS_A_SECRET"
447+
if err := os.WriteFile(secretPath, []byte(secretLine+"\n"), 0600); err != nil {
448+
t.Fatal(err)
449+
}
450+
451+
err := g.checkout(context.Background(), repo.dir, "--pathspec-from-file="+secretPath)
452+
if err == nil {
453+
t.Fatal("checkout succeeded; want error")
454+
}
455+
if !strings.Contains(err.Error(), "invalid ref") {
456+
t.Fatalf("expected invalid ref error, got: %s", err)
457+
}
458+
if strings.Contains(err.Error(), secretLine) {
459+
t.Fatalf("secret leaked in error message:\n%s", err.Error())
460+
}
461+
}
462+
435463
func TestGitGetter_GetFile(t *testing.T) {
436464
if !testHasGit {
437465
t.Skip("git not found, skipping")

0 commit comments

Comments
 (0)