Skip to content

Commit a881223

Browse files
committed
ADD: Check target path - Security fix
1 parent 78b7511 commit a881223

File tree

4 files changed

+118
-6
lines changed

4 files changed

+118
-6
lines changed

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@ selected branch (in variable REPO_BRANCH) and can be pulled new version on defin
1111

1212
## RELEASE NOTES: v0.0.3-alpha
1313

14-
| Feature | Description |
15-
|---------|---------------------------------------------------|
16-
| Done | Add support to proxy redirect with HTTPS backends |
17-
| FIX | Bump golang.org/x/text from 0.3.7 to 0.3.8 |
18-
14+
| Feature | Description |
15+
|---------|--------------------------------------------------------------------------------------------------------------------|
16+
| Done | Add support to proxy redirect with HTTPS backends |
17+
| FIXED | Bump golang.org/x/text from 0.3.7 to 0.3.8 |
18+
| FIXED | Bump github.com/stretchr/testify from 1.7.0 to 1.7.1 |
19+
| FIXED | Bump golang.org/x/sys from 0.0.0-20220209214540-3681064d5158 to 0.1.0 |
20+
| FIXED | Bump golang.org/x/crypto from 0.0.0-20220214200702-86341886e292 to 0.1.0 |
21+
| FIXED | Bump golang.org/x/net from 0.0.0-20220127200216-cd36cc0744dd to 0.17.0 in |
22+
| FIXED | Vulnerability issue Uncontrolled data used in path [Issue](https://github.com/jarpsimoes/git-http-server/issues/8) |
1923

2024

2125
## Authentication Methods

src/utils/environment_config.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"github.com/go-git/go-git/v5/plumbing/transport/http"
77
"log"
88
"os"
9+
"path/filepath"
10+
"runtime"
911
"sync"
1012
"time"
1113
)
@@ -51,6 +53,11 @@ var baseRouteConfigInstance *BaseRouteConfig
5153
var baseRepositoryConfigInstance *BaseRepositoryConfig
5254
var basicAuthenticationMethod *BasicAuthenticationMethod
5355
var healthCheckControl *HealthCheckControl
56+
var pathSecurityCheck *PathSecurityCheck
57+
var (
58+
_, b, _, _ = runtime.Caller(0)
59+
basePath = filepath.Dir(b)
60+
)
5461

5562
// UpdateState [HealthCheckControl] it's a function to update Status
5663
func (hcc *HealthCheckControl) UpdateState(status bool) {
@@ -183,9 +190,16 @@ func GetRepositoryConfigInstance() *BaseRepositoryConfig {
183190
repoURL: os.Getenv("REPO_URL"),
184191
branch: os.Getenv("REPO_BRANCH"),
185192
targetFolder: os.Getenv("REPO_TARGET_FOLDER"),
186-
rootFolder: os.Getenv("FOLDER_ROOT"),
193+
rootFolder: basePath,
187194
}
188195

196+
if pathSecurityCheck.IsValidPath(baseRepositoryConfigInstance.targetFolder) {
197+
log.Printf("[BaseRepositoryConfigInstance] Target folder %v is valid", baseRepositoryConfigInstance.targetFolder)
198+
} else {
199+
log.Printf("[BaseRepositoryConfigInstance] Target folder %v is invalid", baseRepositoryConfigInstance.targetFolder)
200+
log.Printf("[BaseRepositoryConfigInstance] Will be changed to target")
201+
baseRepositoryConfigInstance.targetFolder = "target_folder"
202+
}
189203
}
190204
}
191205

src/utils/path_security_check.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package utils
2+
3+
import (
4+
"regexp"
5+
)
6+
7+
type PathSecurityCheck struct {
8+
}
9+
10+
// IsValidPath checks if the input string adheres to the specified rules.
11+
func (psc *PathSecurityCheck) IsValidPath(input string) bool {
12+
// Rule 1: Do not allow more than a single "." character.
13+
if countDots := psc.countOccurrences(input, '.'); countDots > 1 {
14+
return false
15+
}
16+
17+
if psc.containsDirectorySeparator(input) {
18+
return false
19+
}
20+
21+
allowList := []*regexp.Regexp{
22+
regexp.MustCompile(`^[a-zA-Z0-9_-]+$`), // Alphanumeric characters, underscore, and hyphen.
23+
regexp.MustCompile(`^([a-zA-Z0-9_-]+\.){0,2}[a-zA-Z0-9_-]+$`), // Allow up to two dots in the filename.
24+
}
25+
26+
for _, pattern := range allowList {
27+
if pattern.MatchString(input) {
28+
return true
29+
}
30+
}
31+
32+
return false
33+
}
34+
35+
// countOccurrences counts the occurrences of a specific character in a string.
36+
func (psc *PathSecurityCheck) countOccurrences(s string, c byte) int {
37+
count := 0
38+
for i := 0; i < len(s); i++ {
39+
if s[i] == c {
40+
count++
41+
}
42+
}
43+
return count
44+
}
45+
46+
// containsDirectorySeparator checks if the input string contains directory separators.
47+
func (psc *PathSecurityCheck) containsDirectorySeparator(s string) bool {
48+
return psc.containsAny(s, []byte{'/', '\\'})
49+
}
50+
51+
// containsAny checks if the input string contains any of the specified characters.
52+
func (psc *PathSecurityCheck) containsAny(s string, chars []byte) bool {
53+
for i := 0; i < len(s); i++ {
54+
for _, c := range chars {
55+
if s[i] == c {
56+
return true
57+
}
58+
}
59+
}
60+
return false
61+
}

src/utils/path_security_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package utils
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestIsValidPath(t *testing.T) {
8+
tests := []struct {
9+
input string
10+
expected bool
11+
}{
12+
{"valid_path123", true},
13+
{"invalid_path/with_slash", false},
14+
{"invalid_path/with/slash", false},
15+
{"invalid/path/with/slash", false},
16+
{"invalid.path.with.multiple.dots", false},
17+
{"another.invalid.path.with.multiple.dots", false},
18+
{"valid_path_with_underscore", true},
19+
{"valid-path_with-hyphen", true},
20+
{"valid.path_with_underscore-hyphen", true},
21+
}
22+
23+
pathSecurityCheck := PathSecurityCheck{}
24+
25+
for _, test := range tests {
26+
t.Run(test.input, func(t *testing.T) {
27+
result := pathSecurityCheck.IsValidPath(test.input)
28+
if result != test.expected {
29+
t.Errorf("Expected IsValidPath(%s) to be %v, but got %v", test.input, test.expected, result)
30+
}
31+
})
32+
}
33+
}

0 commit comments

Comments
 (0)