@@ -1248,6 +1248,45 @@ func (r *gitRepo) latestCommit() (string, error) {
12481248 return string (rawOut ), nil
12491249}
12501250
1251+ // Test checkout ref option injection to verify that if a user tries to inject a git option
1252+ func TestGitGetter_checkoutRefOptionInjectionRejected (t * testing.T ) {
1253+ if ! testHasGit {
1254+ t .Skip ("git not found, skipping" )
1255+ }
1256+
1257+ g := new (GitGetter )
1258+ repo := testGitRepo (t , "empty-repo" )
1259+ repo .git ("config" , "commit.gpgsign" , "false" )
1260+ repo .commitFile ("safe.txt" , "safe" )
1261+
1262+ // Create a fake "secret" file to simulate sensitive data
1263+ secretPath := filepath .Join (t .TempDir (), "secret.txt" )
1264+ secretLine := "THIS_IS_A_SECRET"
1265+ if err := os .WriteFile (secretPath , []byte (secretLine + "\n " ), 0600 ); err != nil {
1266+ t .Fatal (err )
1267+ }
1268+
1269+ // Attempt to inject a git option
1270+ ref := "--pathspec-from-file=" + secretPath
1271+
1272+ err := g .checkout (context .Background (), repo .dir , ref )
1273+
1274+ // Expect error due to validation (not git execution)
1275+ if err == nil {
1276+ t .Fatal ("expected error for invalid ref, got nil" )
1277+ }
1278+
1279+ // Ensure it's our validation error, not git output
1280+ if ! strings .Contains (err .Error (), "invalid ref" ) {
1281+ t .Fatalf ("expected validation error, got: %v" , err )
1282+ }
1283+
1284+ // Ensure secret is NOT leaked
1285+ if strings .Contains (err .Error (), secretLine ) {
1286+ t .Fatalf ("secret leaked in error message:\n %s" , err .Error ())
1287+ }
1288+ }
1289+
12511290// This is a read-only deploy key for an empty test repository.
12521291// Note: This is split over multiple lines to avoid being disabled by key
12531292// scanners automatically.
0 commit comments