Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 79b7f24

Browse files
committed
config: modules, Ignore submodules with dotdot '..' path components. Fixes CVE-2018-11235
References: * https://blogs.msdn.microsoft.com/devops/2018/05/29/announcing-the-may-2018-git-security-vulnerability/ * https://security-tracker.debian.org/tracker/CVE-2018-11235 * git/git@0383bbb Signed-off-by: Joseph Vusich <jvusich@amazon.com>
1 parent 57570e8 commit 79b7f24

File tree

3 files changed

+46
-12
lines changed

3 files changed

+46
-12
lines changed

config/config.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ func (c *Config) Unmarshal(b []byte) error {
135135
if err := c.unmarshalPack(); err != nil {
136136
return err
137137
}
138-
c.unmarshalSubmodules()
138+
unmarshalSubmodules(c.Raw, c.Submodules)
139139

140140
if err := c.unmarshalBranches(); err != nil {
141141
return err
@@ -182,13 +182,17 @@ func (c *Config) unmarshalRemotes() error {
182182
return nil
183183
}
184184

185-
func (c *Config) unmarshalSubmodules() {
186-
s := c.Raw.Section(submoduleSection)
185+
func unmarshalSubmodules(fc *format.Config, submodules map[string]*Submodule) {
186+
s := fc.Section(submoduleSection)
187187
for _, sub := range s.Subsections {
188188
m := &Submodule{}
189189
m.unmarshal(sub)
190190

191-
c.Submodules[m.Name] = m
191+
if m.Validate() == ErrModuleBadPath {
192+
continue
193+
}
194+
195+
submodules[m.Name] = m
192196
}
193197
}
194198

config/modules.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@ package config
33
import (
44
"bytes"
55
"errors"
6+
"regexp"
67

78
format "gopkg.in/src-d/go-git.v4/plumbing/format/config"
89
)
910

1011
var (
1112
ErrModuleEmptyURL = errors.New("module config: empty URL")
1213
ErrModuleEmptyPath = errors.New("module config: empty path")
14+
ErrModuleBadPath = errors.New("submodule has an invalid path")
15+
)
16+
17+
var (
18+
// Matches module paths with dotdot ".." components.
19+
dotdotPath = regexp.MustCompile(`(^|[/\\])\.\.([/\\]|$)`)
1320
)
1421

1522
// Modules defines the submodules properties, represents a .gitmodules file
@@ -44,14 +51,7 @@ func (m *Modules) Unmarshal(b []byte) error {
4451
return err
4552
}
4653

47-
s := m.raw.Section(submoduleSection)
48-
for _, sub := range s.Subsections {
49-
mod := &Submodule{}
50-
mod.unmarshal(sub)
51-
52-
m.Submodules[mod.Path] = mod
53-
}
54-
54+
unmarshalSubmodules(m.raw, m.Submodules)
5555
return nil
5656
}
5757

@@ -102,6 +102,10 @@ func (m *Submodule) Validate() error {
102102
return ErrModuleEmptyURL
103103
}
104104

105+
if dotdotPath.MatchString(m.Path) {
106+
return ErrModuleBadPath
107+
}
108+
105109
return nil
106110
}
107111

config/modules_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,29 @@ func (s *ModulesSuite) TestValidateMissingURL(c *C) {
1111
c.Assert(m.Validate(), Equals, ErrModuleEmptyURL)
1212
}
1313

14+
func (s *ModulesSuite) TestValidateBadPath(c *C) {
15+
input := []string{
16+
`..`,
17+
`../`,
18+
`../bar`,
19+
20+
`/..`,
21+
`/../bar`,
22+
23+
`foo/..`,
24+
`foo/../`,
25+
`foo/../bar`,
26+
}
27+
28+
for _, p := range input {
29+
m := &Submodule{
30+
Path: p,
31+
URL: "https://example.com/",
32+
}
33+
c.Assert(m.Validate(), Equals, ErrModuleBadPath)
34+
}
35+
}
36+
1437
func (s *ModulesSuite) TestValidateMissingName(c *C) {
1538
m := &Submodule{URL: "bar"}
1639
c.Assert(m.Validate(), Equals, ErrModuleEmptyPath)
@@ -39,6 +62,9 @@ func (s *ModulesSuite) TestUnmarshall(c *C) {
3962
path = foo/bar
4063
url = https://github.com/foo/bar.git
4164
branch = dev
65+
[submodule "suspicious"]
66+
path = ../../foo/bar
67+
url = https://github.com/foo/bar.git
4268
`)
4369

4470
cfg := NewModules()

0 commit comments

Comments
 (0)