Skip to content

Commit

Permalink
Fixed the zip slip
Browse files Browse the repository at this point in the history
- Fixed the zip slip
  • Loading branch information
naveensrinivasan committed Nov 22, 2024
1 parent b320e2e commit d56c51b
Showing 1 changed file with 50 additions and 7 deletions.
57 changes: 50 additions & 7 deletions cmd/helpers/fileLoader.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"
"os"
"path/filepath"
"strings"
)

// LoadDataFromPath takes in a directory or file path and processes the data into the storage.
Expand Down Expand Up @@ -68,6 +69,7 @@ func LoadDataFromPath(path string) ([]Data, error) {
return result, nil
}

// processZipFile safely extracts files from a ZIP archive, preventing Zip Slip.
func processZipFile(filePath string) ([]Data, error) {
r, err := zip.OpenReader(filePath)
if err != nil {
Expand All @@ -79,24 +81,65 @@ func processZipFile(filePath string) ([]Data, error) {
if err != nil {
return nil, fmt.Errorf("failed to create temp directory: %w", err)
}
defer os.RemoveAll(tempDir)
// Ensure the temp directory is removed in case of an error.
defer func() {
if err != nil {
os.RemoveAll(tempDir)
}

Check warning on line 88 in cmd/helpers/fileLoader.go

View check run for this annotation

Codecov / codecov/patch

cmd/helpers/fileLoader.go#L85-L88

Added lines #L85 - L88 were not covered by tests
}()

for _, f := range r.File {
// Clean the file name to remove any path traversal.
cleanName := filepath.Clean(f.Name)

// Prevent absolute paths.
if filepath.IsAbs(cleanName) {
return nil, fmt.Errorf("invalid file path %s: absolute paths are not allowed", f.Name)
}

Check warning on line 98 in cmd/helpers/fileLoader.go

View check run for this annotation

Codecov / codecov/patch

cmd/helpers/fileLoader.go#L92-L98

Added lines #L92 - L98 were not covered by tests

// Resolve the absolute path.
extractedFilePath := filepath.Join(tempDir, cleanName)
absExtractedPath, err := filepath.Abs(extractedFilePath)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path for %s: %w", extractedFilePath, err)
}

Check warning on line 105 in cmd/helpers/fileLoader.go

View check run for this annotation

Codecov / codecov/patch

cmd/helpers/fileLoader.go#L101-L105

Added lines #L101 - L105 were not covered by tests

absTempDir, err := filepath.Abs(tempDir)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path for temp directory: %w", err)
}

Check warning on line 110 in cmd/helpers/fileLoader.go

View check run for this annotation

Codecov / codecov/patch

cmd/helpers/fileLoader.go#L107-L110

Added lines #L107 - L110 were not covered by tests

// Ensure that the extracted path is within the temp directory.
if !strings.HasPrefix(absExtractedPath, absTempDir+string(os.PathSeparator)) {
return nil, fmt.Errorf("invalid file path %s: outside of the extraction directory", f.Name)
}

Check warning on line 115 in cmd/helpers/fileLoader.go

View check run for this annotation

Codecov / codecov/patch

cmd/helpers/fileLoader.go#L113-L115

Added lines #L113 - L115 were not covered by tests

// Create necessary directories.
if f.FileInfo().IsDir() {
if err := os.MkdirAll(absExtractedPath, os.ModePerm); err != nil {
return nil, fmt.Errorf("failed to create directory %s: %w", absExtractedPath, err)
}
continue
} else {
if err := os.MkdirAll(filepath.Dir(absExtractedPath), os.ModePerm); err != nil {
return nil, fmt.Errorf("failed to create directory for file %s: %w", absExtractedPath, err)
}

Check warning on line 126 in cmd/helpers/fileLoader.go

View check run for this annotation

Codecov / codecov/patch

cmd/helpers/fileLoader.go#L118-L126

Added lines #L118 - L126 were not covered by tests
}

rc, err := f.Open()
if err != nil {
return nil, fmt.Errorf("failed to open file %s in zip: %w", f.Name, err)
}
defer rc.Close()

extractedFilePath := filepath.Join(tempDir, f.Name)
outFile, err := os.Create(extractedFilePath)
outFile, err := os.Create(absExtractedPath)

Check warning on line 135 in cmd/helpers/fileLoader.go

View check run for this annotation

Codecov / codecov/patch

cmd/helpers/fileLoader.go#L135

Added line #L135 was not covered by tests
if err != nil {
return nil, fmt.Errorf("failed to create file %s: %w", extractedFilePath, err)
return nil, fmt.Errorf("failed to create file %s: %w", absExtractedPath, err)

Check warning on line 137 in cmd/helpers/fileLoader.go

View check run for this annotation

Codecov / codecov/patch

cmd/helpers/fileLoader.go#L137

Added line #L137 was not covered by tests
}
defer outFile.Close()
_, err = io.Copy(outFile, rc)
if err != nil {
return nil, fmt.Errorf("failed to copy file %s: %w", extractedFilePath, err)

if _, err := io.Copy(outFile, rc); err != nil {
return nil, fmt.Errorf("failed to copy file %s: %w", absExtractedPath, err)

Check warning on line 142 in cmd/helpers/fileLoader.go

View check run for this annotation

Codecov / codecov/patch

cmd/helpers/fileLoader.go#L140-L142

Added lines #L140 - L142 were not covered by tests
}
}

Expand Down

0 comments on commit d56c51b

Please sign in to comment.