diff --git a/.gitignore b/.gitignore index 4ba0c66..25abbcf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *~ +.idea *.DS* *.zip *.rar diff --git a/7z.go b/7z.go index d4faa9a..8ffce22 100644 --- a/7z.go +++ b/7z.go @@ -68,10 +68,10 @@ func extract7z(xFile *XFile) (int64, []string, []string, error) { if err != nil { lastFile := xFile.FilePath /* // https://github.com/bodgit/sevenzip/issues/54 - // We can probably never get the file with the error. - if volumes := sevenZip.Volumes(); len(volumes) > 0 { - lastFile = volumes[len(volumes)-1] - } */ + // We can probably never get the file with the error. + if volumes := sevenZip.Volumes(); len(volumes) > 0 { + lastFile = volumes[len(volumes)-1] + } */ return size, files, sevenZip.Volumes(), fmt.Errorf("%s: %w", lastFile, err) } @@ -84,7 +84,8 @@ func extract7z(xFile *XFile) (int64, []string, []string, error) { func (x *XFile) un7zip(zipFile *sevenzip.File) (int64, error) { //nolint:dupl wfile := x.clean(zipFile.Name) - if !strings.HasPrefix(wfile, x.OutputDir) { + outputDir := filepath.Clean(x.OutputDir) + if !strings.HasPrefix(wfile, outputDir) { // The file being written is trying to write outside of our base path. Malicious archive? return 0, fmt.Errorf("%s: %w: %s (from: %s)", zipFile.FileInfo().Name(), ErrInvalidPath, wfile, zipFile.Name) } diff --git a/iso.go b/iso.go index eff7d3d..35a8174 100644 --- a/iso.go +++ b/iso.go @@ -69,8 +69,9 @@ func (x *XFile) uniso(isoFile *iso9660.File, parent string) (int64, []string, er func (x *XFile) unisofile(isoFile *iso9660.File, fileName string) (int64, []string, error) { destFile := x.clean(fileName) - //nolint:gocritic // this 1-argument filepath.Join removes a ./ prefix should there be one. - if !strings.HasPrefix(destFile, filepath.Join(x.OutputDir)) { + outputDir := filepath.Clean(x.OutputDir) + //nolint:gocritic // this 1-argument filepath.Clean removes a ./ prefix should there be one. + if !strings.HasPrefix(destFile, outputDir) { // The file being written is trying to write outside of our base path. Malicious ISO? return 0, nil, fmt.Errorf("%s: %w: %s != %s (from: %s)", x.FilePath, ErrInvalidPath, destFile, x.OutputDir, isoFile.Name()) diff --git a/rar.go b/rar.go index 7627f36..fa2ef85 100644 --- a/rar.go +++ b/rar.go @@ -92,8 +92,9 @@ func (x *XFile) unrar(rarReader *rardecode.ReadCloser) (int64, []string, error) } wfile := x.clean(header.Name) - //nolint:gocritic // this 1-argument filepath.Join removes a ./ prefix should there be one. - if !strings.HasPrefix(wfile, filepath.Join(x.OutputDir)) { + outputDir := filepath.Clean(x.OutputDir) + //nolint:gocritic // this 1-argument filepath.Clean removes a ./ prefix should there be one. + if !strings.HasPrefix(wfile, outputDir) { // The file being written is trying to write outside of our base path. Malicious archive? return size, files, fmt.Errorf("%s: %w: %s != %s (from: %s)", x.FilePath, ErrInvalidPath, wfile, x.OutputDir, header.Name) diff --git a/tar.go b/tar.go index 1187ce2..a22c185 100644 --- a/tar.go +++ b/tar.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "os" + "path/filepath" "strings" lzw "github.com/sshaman1101/dcompress" @@ -102,7 +103,8 @@ func (x *XFile) untar(tarReader *tar.Reader) (int64, []string, error) { } wfile := x.clean(header.Name) - if !strings.HasPrefix(wfile, x.OutputDir) { + outputDir := filepath.Clean(x.OutputDir) + if !strings.HasPrefix(wfile, outputDir) { // The file being written is trying to write outside of our base path. Malicious archive? return size, files, fmt.Errorf("%s: %w: %s (from: %s)", x.FilePath, ErrInvalidPath, wfile, header.Name) } diff --git a/zip.go b/zip.go index 3bee51f..c341ce1 100644 --- a/zip.go +++ b/zip.go @@ -1,64 +1,65 @@ package xtractr import ( - "archive/zip" - "fmt" - "os" - "path/filepath" - "strings" + "archive/zip" + "fmt" + "os" + "path/filepath" + "strings" ) /* How to extract a ZIP file. */ // ExtractZIP extracts a zip file.. to a destination. Simple enough. func ExtractZIP(xFile *XFile) (int64, []string, error) { - zipReader, err := zip.OpenReader(xFile.FilePath) - if err != nil { - return 0, nil, fmt.Errorf("zip.OpenReader: %w", err) - } - defer zipReader.Close() + zipReader, err := zip.OpenReader(xFile.FilePath) + if err != nil { + return 0, nil, fmt.Errorf("zip.OpenReader: %w", err) + } + defer zipReader.Close() - files := []string{} - size := int64(0) + files := []string{} + size := int64(0) - for _, zipFile := range zipReader.Reader.File { - fSize, err := xFile.unzip(zipFile) - if err != nil { - return size, files, fmt.Errorf("%s: %w", xFile.FilePath, err) - } + for _, zipFile := range zipReader.Reader.File { + fSize, err := xFile.unzip(zipFile) + if err != nil { + return size, files, fmt.Errorf("%s: %w", xFile.FilePath, err) + } - files = append(files, filepath.Join(xFile.OutputDir, zipFile.Name)) //nolint: gosec - size += fSize - } + files = append(files, filepath.Join(xFile.OutputDir, zipFile.Name)) //nolint:gosec + size += fSize + } - return size, files, nil + return size, files, nil } func (x *XFile) unzip(zipFile *zip.File) (int64, error) { //nolint:dupl - wfile := x.clean(zipFile.Name) - if !strings.HasPrefix(wfile, x.OutputDir) { - // The file being written is trying to write outside of our base path. Malicious archive? - return 0, fmt.Errorf("%s: %w: %s (from: %s)", zipFile.FileInfo().Name(), ErrInvalidPath, wfile, zipFile.Name) - } + wfile := x.clean(zipFile.Name) + outputDir := filepath.Clean(x.OutputDir) + if !strings.HasPrefix(wfile, outputDir) { + // The file being written is trying to write outside of our base path. Malicious archive? + return 0, fmt.Errorf("%s: %w: %s (from: %s)", zipFile.FileInfo().Name(), ErrInvalidPath, wfile, zipFile.Name) + } - if strings.HasSuffix(wfile, "/") || zipFile.FileInfo().IsDir() { - if err := os.MkdirAll(wfile, x.DirMode); err != nil { - return 0, fmt.Errorf("making zipFile dir: %w", err) - } + if strings.HasSuffix(wfile, "/") || zipFile.FileInfo().IsDir() { + if err := os.MkdirAll(wfile, x.DirMode); err != nil { + return 0, fmt.Errorf("making zipFile dir: %w", err) + } - return 0, nil - } + return 0, nil + } - zFile, err := zipFile.Open() - if err != nil { - return 0, fmt.Errorf("zipFile.Open: %w", err) - } - defer zFile.Close() + zFile, err := zipFile.Open() + if err != nil { + return 0, fmt.Errorf("zipFile.Open: %w", err) + } + defer zFile.Close() - s, err := writeFile(wfile, zFile, x.FileMode, x.DirMode) - if err != nil { - return s, fmt.Errorf("%s: %w: %s (from: %s)", zipFile.FileInfo().Name(), err, wfile, zipFile.Name) - } + s, err := writeFile(wfile, zFile, x.FileMode, x.DirMode) + if err != nil { + return s, fmt.Errorf("%s: %w: %s (from: %s)", zipFile.FileInfo().Name(), err, wfile, zipFile.Name) + } - return s, nil + return s, nil }