Skip to content

Commit 594bb81

Browse files
committed
sec: added --end-of-options to prevent unintended options
Signed-off-by: Carlos Alexandro Becker <[email protected]>
1 parent 6673f38 commit 594bb81

File tree

8 files changed

+33
-16
lines changed

8 files changed

+33
-16
lines changed

repo.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ func Init(path string, opts ...InitOptions) error {
8383
if opt.Bare {
8484
cmd.AddArgs("--bare")
8585
}
86+
cmd.AddArgs("--end-of-options")
8687
_, err = cmd.RunInDirWithTimeout(opt.Timeout, path)
8788
return err
8889
}
@@ -157,6 +158,7 @@ func Clone(url, dst string, opts ...CloneOptions) error {
157158
cmd.AddArgs("--depth", strconv.FormatUint(opt.Depth, 10))
158159
}
159160

161+
cmd.AddArgs("--end-of-options")
160162
_, err = cmd.AddArgs(url, dst).RunWithTimeout(opt.Timeout)
161163
return err
162164
}
@@ -259,7 +261,7 @@ func Push(repoPath, remote, branch string, opts ...PushOptions) error {
259261
opt = opts[0]
260262
}
261263

262-
cmd := NewCommand("push").AddOptions(opt.CommandOptions).AddArgs(remote, branch)
264+
cmd := NewCommand("push").AddOptions(opt.CommandOptions).AddArgs("--end-of-options", remote, branch)
263265
_, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath)
264266
return err
265267
}
@@ -346,7 +348,7 @@ func Reset(repoPath, rev string, opts ...ResetOptions) error {
346348
cmd.AddArgs("--hard")
347349
}
348350

349-
_, err := cmd.AddOptions(opt.CommandOptions).AddArgs(rev).RunInDir(repoPath)
351+
_, err := cmd.AddOptions(opt.CommandOptions).AddArgs("--end-of-options", rev).RunInDir(repoPath)
350352
return err
351353
}
352354

@@ -382,7 +384,7 @@ func Move(repoPath, src, dst string, opts ...MoveOptions) error {
382384
opt = opts[0]
383385
}
384386

385-
_, err := NewCommand("mv").AddOptions(opt.CommandOptions).AddArgs(src, dst).RunInDirWithTimeout(opt.Timeout, repoPath)
387+
_, err := NewCommand("mv").AddOptions(opt.CommandOptions).AddArgs("--end-of-options", src, dst).RunInDirWithTimeout(opt.Timeout, repoPath)
386388
return err
387389
}
388390

@@ -549,7 +551,7 @@ func ShowNameStatus(repoPath, rev string, opts ...ShowNameStatusOptions) (*NameS
549551
stderr := new(bytes.Buffer)
550552
cmd := NewCommand("show", "--name-status", "--pretty=format:''").
551553
AddOptions(opt.CommandOptions).
552-
AddArgs(rev)
554+
AddArgs("--end-of-options", rev)
553555
err := cmd.RunInDirPipelineWithTimeout(opt.Timeout, w, stderr, repoPath)
554556
_ = w.Close() // Close writer to exit parsing goroutine
555557
if err != nil {

repo_commit.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ func (r *Repository) Log(rev string, opts ...LogOptions) ([]*Commit, error) {
221221

222222
cmd := NewCommand("log").
223223
AddOptions(opt.CommandOptions).
224-
AddArgs("--pretty="+LogFormatHashOnly, rev)
224+
AddArgs("--pretty=" + LogFormatHashOnly)
225225
if opt.MaxCount > 0 {
226226
cmd.AddArgs("--max-count=" + strconv.Itoa(opt.MaxCount))
227227
}
@@ -237,6 +237,7 @@ func (r *Repository) Log(rev string, opts ...LogOptions) ([]*Commit, error) {
237237
if opt.RegexpIgnoreCase {
238238
cmd.AddArgs("--regexp-ignore-case")
239239
}
240+
cmd.AddArgs("--end-of-options", rev)
240241
cmd.AddArgs("--")
241242
if opt.Path != "" {
242243
cmd.AddArgs(escapePath(opt.Path))
@@ -406,6 +407,7 @@ func DiffNameOnly(repoPath, base, head string, opts ...DiffNameOnlyOptions) ([]s
406407
cmd := NewCommand("diff").
407408
AddOptions(opt.CommandOptions).
408409
AddArgs("--name-only")
410+
cmd.AddArgs("--end-of-options")
409411
if opt.NeedsMergeBase {
410412
cmd.AddArgs(base + "..." + head)
411413
} else {
@@ -471,7 +473,8 @@ func (r *Repository) RevListCount(refspecs []string, opts ...RevListCountOptions
471473

472474
cmd := NewCommand("rev-list").
473475
AddOptions(opt.CommandOptions).
474-
AddArgs("--count")
476+
AddArgs("--count").
477+
AddArgs("--end-of-options")
475478
cmd.AddArgs(refspecs...)
476479
cmd.AddArgs("--")
477480
if opt.Path != "" {
@@ -512,6 +515,7 @@ func (r *Repository) RevList(refspecs []string, opts ...RevListOptions) ([]*Comm
512515
}
513516

514517
cmd := NewCommand("rev-list").AddOptions(opt.CommandOptions)
518+
cmd.AddArgs("--end-of-options")
515519
cmd.AddArgs(refspecs...)
516520
cmd.AddArgs("--")
517521
if opt.Path != "" {

repo_diff.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,20 @@ func (r *Repository) Diff(rev string, maxFiles, maxFileLines, maxLineChars int,
4545
if commit.ParentsCount() == 0 {
4646
cmd = cmd.AddArgs("show").
4747
AddOptions(opt.CommandOptions).
48-
AddArgs("--full-index", rev)
48+
AddArgs("--full-index", "--end-of-options", rev)
4949
} else {
5050
c, err := commit.Parent(0)
5151
if err != nil {
5252
return nil, err
5353
}
5454
cmd = cmd.AddArgs("diff").
5555
AddOptions(opt.CommandOptions).
56-
AddArgs("--full-index", "-M", c.ID.String(), rev)
56+
AddArgs("--full-index", "-M", c.ID.String(), "--end-of-options", rev)
5757
}
5858
} else {
5959
cmd = cmd.AddArgs("diff").
6060
AddOptions(opt.CommandOptions).
61-
AddArgs("--full-index", "-M", opt.Base, rev)
61+
AddArgs("--full-index", "-M", opt.Base, "--end-of-options", rev)
6262
}
6363

6464
stdout, w := io.Pipe()
@@ -114,29 +114,29 @@ func (r *Repository) RawDiff(rev string, diffType RawDiffFormat, w io.Writer, op
114114
if commit.ParentsCount() == 0 {
115115
cmd = cmd.AddArgs("show").
116116
AddOptions(opt.CommandOptions).
117-
AddArgs("--full-index", rev)
117+
AddArgs("--full-index", "--end-of-options", rev)
118118
} else {
119119
c, err := commit.Parent(0)
120120
if err != nil {
121121
return err
122122
}
123123
cmd = cmd.AddArgs("diff").
124124
AddOptions(opt.CommandOptions).
125-
AddArgs("--full-index", "-M", c.ID.String(), rev)
125+
AddArgs("--full-index", "-M", c.ID.String(), "--end-of-options", rev)
126126
}
127127
case RawDiffPatch:
128128
if commit.ParentsCount() == 0 {
129129
cmd = cmd.AddArgs("format-patch").
130130
AddOptions(opt.CommandOptions).
131-
AddArgs("--full-index", "--no-signoff", "--no-signature", "--stdout", "--root", rev)
131+
AddArgs("--full-index", "--no-signoff", "--no-signature", "--stdout", "--root", "--end-of-options", rev)
132132
} else {
133133
c, err := commit.Parent(0)
134134
if err != nil {
135135
return err
136136
}
137137
cmd = cmd.AddArgs("format-patch").
138138
AddOptions(opt.CommandOptions).
139-
AddArgs("--full-index", "--no-signoff", "--no-signature", "--stdout", rev+"..."+c.ID.String())
139+
AddArgs("--full-index", "--no-signoff", "--no-signature", "--stdout", "--end-of-options", rev+"..."+c.ID.String())
140140
}
141141
default:
142142
return fmt.Errorf("invalid diffType: %s", diffType)

repo_grep.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ func (r *Repository) Grep(pattern string, opts ...GrepOptions) []*GrepResult {
9696
if opt.ExtendedRegexp {
9797
cmd.AddArgs("--extended-regexp")
9898
}
99+
cmd.AddArgs("--end-of-options")
99100
cmd.AddArgs(pattern, opt.Tree)
100101
if opt.Pathspec != "" {
101102
cmd.AddArgs("--", opt.Pathspec)

repo_pull.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func MergeBase(repoPath, base, head string, opts ...MergeBaseOptions) (string, e
3232

3333
stdout, err := NewCommand("merge-base").
3434
AddOptions(opt.CommandOptions).
35+
AddArgs("--end-of-options").
3536
AddArgs(base, head).
3637
RunInDirWithTimeout(opt.Timeout, repoPath)
3738
if err != nil {

repo_reference.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func ShowRefVerify(repoPath, ref string, opts ...ShowRefVerifyOptions) (string,
5656
opt = opts[0]
5757
}
5858

59-
cmd := NewCommand("show-ref", "--verify", ref).AddOptions(opt.CommandOptions)
59+
cmd := NewCommand("show-ref", "--verify", "--end-of-options", ref).AddOptions(opt.CommandOptions)
6060
stdout, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath)
6161
if err != nil {
6262
if strings.Contains(err.Error(), "not a valid ref") {
@@ -162,6 +162,7 @@ func SymbolicRef(repoPath string, opts ...SymbolicRefOptions) (string, error) {
162162
if opt.Name == "" {
163163
opt.Name = "HEAD"
164164
}
165+
cmd.AddArgs("--end-of-options")
165166
cmd.AddArgs(opt.Name)
166167
if opt.Ref != "" {
167168
cmd.AddArgs(opt.Ref)
@@ -281,6 +282,7 @@ func DeleteBranch(repoPath, name string, opts ...DeleteBranchOptions) error {
281282
} else {
282283
cmd.AddArgs("-d")
283284
}
285+
cmd.AddArgs("--end-of-options")
284286
_, err := cmd.AddArgs(name).RunInDirWithTimeout(opt.Timeout, repoPath)
285287
return err
286288
}

repo_remote.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func LsRemote(url string, opts ...LsRemoteOptions) ([]*Reference, error) {
4949
if opt.Refs {
5050
cmd.AddArgs("--refs")
5151
}
52+
cmd.AddArgs("--end-of-options")
5253
cmd.AddArgs(url)
5354
if len(opt.Patterns) > 0 {
5455
cmd.AddArgs(opt.Patterns...)
@@ -120,6 +121,7 @@ func RemoteAdd(repoPath, name, url string, opts ...RemoteAddOptions) error {
120121
if opt.MirrorFetch {
121122
cmd.AddArgs("--mirror=fetch")
122123
}
124+
cmd.AddArgs("--end-of-options")
123125

124126
_, err := cmd.AddArgs(name, url).RunInDirWithTimeout(opt.Timeout, repoPath)
125127
return err
@@ -166,7 +168,7 @@ func RemoteRemove(repoPath, name string, opts ...RemoteRemoveOptions) error {
166168

167169
_, err := NewCommand("remote", "remove").
168170
AddOptions(opt.CommandOptions).
169-
AddArgs(name).
171+
AddArgs("--end-of-options", name).
170172
RunInDirWithTimeout(opt.Timeout, repoPath)
171173
if err != nil {
172174
// the error status may differ from git clients
@@ -262,6 +264,7 @@ func RemoteGetURL(repoPath, name string, opts ...RemoteGetURLOptions) ([]string,
262264
if opt.All {
263265
cmd.AddArgs("--all")
264266
}
267+
cmd.AddArgs("--end-of-options")
265268

266269
stdout, err := cmd.AddArgs(name).RunInDirWithTimeout(opt.Timeout, repoPath)
267270
if err != nil {
@@ -306,6 +309,7 @@ func RemoteSetURL(repoPath, name, newurl string, opts ...RemoteSetURLOptions) er
306309
cmd.AddArgs("--push")
307310
}
308311

312+
cmd.AddArgs("--end-of-options")
309313
cmd.AddArgs(name, newurl)
310314

311315
if opt.Regex != "" {
@@ -361,6 +365,7 @@ func RemoteSetURLAdd(repoPath, name, newurl string, opts ...RemoteSetURLAddOptio
361365
cmd.AddArgs("--push")
362366
}
363367

368+
cmd.AddArgs("--end-of-options")
364369
cmd.AddArgs(name, newurl)
365370

366371
_, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath)
@@ -407,6 +412,7 @@ func RemoteSetURLDelete(repoPath, name, regex string, opts ...RemoteSetURLDelete
407412
cmd.AddArgs("--push")
408413
}
409414

415+
cmd.AddArgs("--end-of-options")
410416
cmd.AddArgs(name, regex)
411417

412418
_, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath)

repo_tag.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ func (r *Repository) CreateTag(name, rev string, opts ...CreateTagOptions) error
247247
if opt.Author != nil {
248248
cmd.AddCommitter(opt.Author)
249249
}
250+
cmd.AddArgs("--end-of-options")
250251
} else {
251252
// 🚨 SECURITY: Prevent including unintended options in the path to the Git command.
252253
cmd.AddArgs("--end-of-options")
@@ -279,7 +280,7 @@ func (r *Repository) DeleteTag(name string, opts ...DeleteTagOptions) error {
279280
opt = opts[0]
280281
}
281282

282-
_, err := NewCommand("tag", "--delete", name).
283+
_, err := NewCommand("tag", "--delete", "--end-of-options", name).
283284
AddOptions(opt.CommandOptions).
284285
RunInDirWithTimeout(opt.Timeout, r.path)
285286
return err

0 commit comments

Comments
 (0)