diff --git a/repo.go b/repo.go index 140ece35..21d169d4 100644 --- a/repo.go +++ b/repo.go @@ -451,6 +451,15 @@ func (r *Repository) RevParse(ctx context.Context, rev string, opts ...RevParseO opt = opts[0] } + // A revision that starts with a dash is never a valid object and would + // instead be interpreted by "git rev-parse" as a command-line option, + // allowing argument injection. The "--end-of-options" separator does not + // help here because "git rev-parse" does not honor it for revisions, so + // reject such input outright. + if strings.HasPrefix(rev, "-") { + return "", ErrRevisionNotExist + } + args := []string{"rev-parse", rev} commitID, err := exec(ctx, r.path, args, opt.Envs) diff --git a/repo_test.go b/repo_test.go index 6f7e9bd8..0213a0c5 100644 --- a/repo_test.go +++ b/repo_test.go @@ -474,6 +474,19 @@ func TestRepository_RevParse(t *testing.T) { expID: "", expErr: ErrRevisionNotExist, }, + + // A revision starting with a dash must be rejected to prevent argument + // injection into "git rev-parse". + { + rev: "--absolute-git-dir", + expID: "", + expErr: ErrRevisionNotExist, + }, + { + rev: "-h", + expID: "", + expErr: ErrRevisionNotExist, + }, } for _, test := range tests { t.Run("", func(t *testing.T) {