diff options
author | dappelt <dappelt@gitlab.com> | 2020-01-07 19:49:27 +0300 |
---|---|---|
committer | dappelt <dappelt@gitlab.com> | 2020-01-07 19:49:27 +0300 |
commit | ae83ae14129fb2683bbc83587df056c79e182679 (patch) | |
tree | d277d4ec90268a9423adc06f7028d63c45d27371 | |
parent | afdd436d7eddd97854489151f1bd1e287908b371 (diff) |
Check that user-provided paths are inside the expected dirda-path-traversal
-rw-r--r-- | internal/cache/keyer.go | 2 | ||||
-rw-r--r-- | internal/helper/repo.go | 4 | ||||
-rw-r--r-- | internal/helper/security.go | 12 | ||||
-rw-r--r-- | internal/helper/security_test.go | 2 | ||||
-rw-r--r-- | internal/service/repository/archive.go | 3 | ||||
-rw-r--r-- | internal/service/repository/rename.go | 4 |
6 files changed, 11 insertions, 16 deletions
diff --git a/internal/cache/keyer.go b/internal/cache/keyer.go index 86957c3fe..4cf8bdbef 100644 --- a/internal/cache/keyer.go +++ b/internal/cache/keyer.go @@ -240,7 +240,7 @@ func getRepoStatePath(repo *gitalypb.Repository) (string, error) { return "", fmt.Errorf("getRepoStatePath: relative path missing from %+v", repo) } - if helper.ContainsPathTraversal(relativePath) { + if helper.ContainsPathTraversal(stateDir, relativePath) { return "", fmt.Errorf("getRepoStatePath: relative path can't contain directory traversal") } diff --git a/internal/helper/repo.go b/internal/helper/repo.go index 9274949a4..3bea9c516 100644 --- a/internal/helper/repo.go +++ b/internal/helper/repo.go @@ -50,7 +50,7 @@ func GetPath(repo repository.GitRepo) (string, error) { return "", err } - if ContainsPathTraversal(relativePath) { + if ContainsPathTraversal(storagePath, relativePath) { return "", status.Errorf(codes.InvalidArgument, "GetRepoPath: relative path can't contain directory traversal") } @@ -109,7 +109,7 @@ func GetObjectDirectoryPath(repo repository.GitRepo) (string, error) { return "", status.Errorf(codes.InvalidArgument, "GetObjectDirectoryPath: empty directory") } - if ContainsPathTraversal(objectDirectoryPath) { + if ContainsPathTraversal(repoPath, objectDirectoryPath) { return "", status.Errorf(codes.InvalidArgument, "GetObjectDirectoryPath: relative path can't contain directory traversal") } diff --git a/internal/helper/security.go b/internal/helper/security.go index e66186580..a6df6546a 100644 --- a/internal/helper/security.go +++ b/internal/helper/security.go @@ -2,18 +2,16 @@ package helper import ( "errors" - "os" + "path" "regexp" "strings" ) -// ContainsPathTraversal checks if the path contains any traversal -func ContainsPathTraversal(path string) bool { +// ContainsPathTraversal checks if relPath contains any traversal +func ContainsPathTraversal(baseDir string, relPath string) bool { // Disallow directory traversal for security - separator := string(os.PathSeparator) - return strings.HasPrefix(path, ".."+separator) || - strings.Contains(path, separator+".."+separator) || - strings.HasSuffix(path, separator+"..") + absPath := path.Clean((path.Join(baseDir, relPath))) + return !strings.HasPrefix(absPath, baseDir) } // Pattern taken from Regular Expressions Cookbook, slightly modified though diff --git a/internal/helper/security_test.go b/internal/helper/security_test.go index 9a8125dac..12b909577 100644 --- a/internal/helper/security_test.go +++ b/internal/helper/security_test.go @@ -19,7 +19,7 @@ func TestContainsPathTraversal(t *testing.T) { } for _, tc := range testCases { - assert.Equal(t, tc.containsTraversal, ContainsPathTraversal(tc.path)) + assert.Equal(t, tc.containsTraversal, ContainsPathTraversal("/repo/storage/path", tc.path)) } } diff --git a/internal/service/repository/archive.go b/internal/service/repository/archive.go index 3b4ca3630..36d6b47d5 100644 --- a/internal/service/repository/archive.go +++ b/internal/service/repository/archive.go @@ -67,7 +67,8 @@ func validateGetArchiveRequest(in *gitalypb.GetArchiveRequest, format string, pa return helper.ErrInvalidArgumentf("invalid format") } - if helper.ContainsPathTraversal(path) { + repoPath, _ := helper.GetRepoPath(in.GetRepository()) + if helper.ContainsPathTraversal(repoPath, path) { return helper.ErrInvalidArgumentf("path can't contain directory traversal") } diff --git a/internal/service/repository/rename.go b/internal/service/repository/rename.go index 10bbee028..d25ef872f 100644 --- a/internal/service/repository/rename.go +++ b/internal/service/repository/rename.go @@ -49,9 +49,5 @@ func validateRenameRepositoryRequest(in *gitalypb.RenameRepositoryRequest) error return errors.New("destination relative path is empty") } - if helper.ContainsPathTraversal(in.GetRelativePath()) { - return errors.New("relative_path contains path traversal") - } - return nil } |