@@ -432,6 +432,126 @@ 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+
463+ func TestGitGetter_checkoutRefLocalBranchResolved (t * testing.T ) {
464+ if ! testHasGit {
465+ t .Skip ("git not found, skipping" )
466+ }
467+
468+ g := new (GitGetter )
469+ repo := testGitRepo (t , "local-branch-repo" )
470+ repo .git ("config" , "commit.gpgsign" , "false" )
471+ repo .commitFile ("base.txt" , "base" )
472+ repo .git ("checkout" , "-b" , "test-branch" )
473+ repo .commitFile ("branch.txt" , "branch" )
474+ wantCommit , err := repo .latestCommit ()
475+ if err != nil {
476+ t .Fatal (err )
477+ }
478+ repo .git ("checkout" , "HEAD~1" )
479+
480+ err = g .checkout (context .Background (), repo .dir , "test-branch" )
481+ if err != nil {
482+ t .Fatalf ("checkout failed: %s" , err )
483+ }
484+
485+ gotCommit , err := repo .latestCommit ()
486+ if err != nil {
487+ t .Fatal (err )
488+ }
489+ if gotCommit != wantCommit {
490+ t .Fatalf ("wrong commit checked out: got %s want %s" , gotCommit , wantCommit )
491+ }
492+ }
493+
494+ func TestGitGetter_checkoutRefHEADResolved (t * testing.T ) {
495+ if ! testHasGit {
496+ t .Skip ("git not found, skipping" )
497+ }
498+
499+ g := new (GitGetter )
500+ repo := testGitRepo (t , "head-repo" )
501+ repo .git ("config" , "commit.gpgsign" , "false" )
502+ repo .commitFile ("head.txt" , "head" )
503+ wantCommit , err := repo .latestCommit ()
504+ if err != nil {
505+ t .Fatal (err )
506+ }
507+
508+ err = g .checkout (context .Background (), repo .dir , "HEAD" )
509+ if err != nil {
510+ t .Fatalf ("checkout failed: %s" , err )
511+ }
512+
513+ gotCommit , err := repo .latestCommit ()
514+ if err != nil {
515+ t .Fatal (err )
516+ }
517+ if gotCommit != wantCommit {
518+ t .Fatalf ("wrong commit checked out: got %s want %s" , gotCommit , wantCommit )
519+ }
520+ }
521+
522+ func TestGitGetter_checkoutRefShellMetacharactersRejected (t * testing.T ) {
523+ if ! testHasGit {
524+ t .Skip ("git not found, skipping" )
525+ }
526+
527+ g := new (GitGetter )
528+ repo := testGitRepo (t , "shell-meta-repo" )
529+ repo .git ("config" , "commit.gpgsign" , "false" )
530+ repo .commitFile ("safe.txt" , "safe" )
531+
532+ tmpDir := t .TempDir ()
533+ markerPath := filepath .Join (tmpDir , "created-by-shell" )
534+ secretPath := filepath .Join (tmpDir , "secret.txt" )
535+ secretLine := "THIS_IS_A_SECRET"
536+ if err := os .WriteFile (secretPath , []byte (secretLine + "\n " ), 0600 ); err != nil {
537+ t .Fatal (err )
538+ }
539+
540+ err := g .checkout (context .Background (), repo .dir , "main | touch " + markerPath )
541+ if err == nil {
542+ t .Fatal ("checkout succeeded; want error" )
543+ }
544+ if ! strings .Contains (err .Error (), "invalid ref" ) {
545+ t .Fatalf ("expected invalid ref error, got: %s" , err )
546+ }
547+ if strings .Contains (err .Error (), secretLine ) {
548+ t .Fatalf ("secret leaked in error message:\n %s" , err .Error ())
549+ }
550+ if _ , err := os .Stat (markerPath ); ! os .IsNotExist (err ) {
551+ t .Fatalf ("shell metacharacters created a file unexpectedly: %v" , err )
552+ }
553+ }
554+
435555func TestGitGetter_GetFile (t * testing.T ) {
436556 if ! testHasGit {
437557 t .Skip ("git not found, skipping" )
0 commit comments