diff --git a/tar/extractor.go b/tar/extractor.go index 4eb479638..70327f47d 100644 --- a/tar/extractor.go +++ b/tar/extractor.go @@ -158,9 +158,14 @@ func (te *Extractor) Extract(reader io.Reader) error { // Checks if the relative path matches or exceeds the root // We check for matching because the outputPath function strips the original root rel, err := fp.Rel(rootOutputPath, outputPath) - if err != nil || rel == "." || strings.Contains(rel, "..") { + if err != nil || rel == "." { return errInvalidRootMultipleRoots } + for _, e := range strings.Split(fp.ToSlash(rel), "/") { + if e == ".." { + return fmt.Errorf("relative path contains '..'") + } + } switch header.Typeflag { case tar.TypeDir: @@ -211,7 +216,7 @@ func getRelativePath(rootName, tarPath string) (string, error) { return tarPath[len(rootName)+1:], nil } -// outputPath returns the path at which to place the relativeTarPath. Assumes the path is cleaned. +// outputPath returns the directory path at which to place the file relativeTarPath. Assumes relativeTarPath is cleaned. func (te *Extractor) outputPath(basePlatformPath, relativeTarPath string) (string, error) { elems := strings.Split(relativeTarPath, "/") diff --git a/tar/extractor_test.go b/tar/extractor_test.go index 4dc3450c9..520859115 100644 --- a/tar/extractor_test.go +++ b/tar/extractor_test.go @@ -45,7 +45,7 @@ func init() { } func TestSingleFile(t *testing.T) { - fileName := "file" + fileName := "file..ext" fileData := "file data" testTarExtraction(t, nil, []tarEntry{ @@ -64,7 +64,7 @@ func TestSingleFile(t *testing.T) { } func TestSingleDirectory(t *testing.T) { - dirName := "dir" + dirName := "dir..sfx" testTarExtraction(t, nil, []tarEntry{ &dirTarEntry{dirName}, diff --git a/tar/sanitize.go b/tar/sanitize.go index a71273707..628e280cb 100644 --- a/tar/sanitize.go +++ b/tar/sanitize.go @@ -20,6 +20,9 @@ func validatePlatformPath(platformPath string) error { } func validatePathComponent(c string) error { + if c == ".." { + return fmt.Errorf("invalid platform path: path component cannot be '..'") + } if strings.Contains(c, "\x00") { return fmt.Errorf("invalid platform path: path components cannot contain null: %q", c) } diff --git a/tar/sanitize_windows.go b/tar/sanitize_windows.go index a659863e6..b313d6e4e 100644 --- a/tar/sanitize_windows.go +++ b/tar/sanitize_windows.go @@ -38,6 +38,9 @@ func validatePathComponent(c string) error { return fmt.Errorf("invalid platform path: path components cannot end with ' ' : %q", c) } + if c == ".." { + return fmt.Errorf("invalid platform path: path component cannot be '..'") + } // error on reserved characters if strings.ContainsAny(c, reservedCharsStr) { return fmt.Errorf("invalid platform path: path components cannot contain any of %s : %q", reservedCharsStr, c)