mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-04 15:49:49 +00:00
fix: sanitize archive entry paths before extraction to prevent path traversal
Move path sanitization before directory handling in extractFile so directory entries with "../" prefixes are rejected the same way file entries already are. Add the same sanitization to extractSevenZipMultiPart and both zip extraction loops in the Windows updater, which had no path validation at all.
This commit is contained in:
1 parent
7c1447f659
commit
022fbf633b
3 files changed
+20
-14
No files matched your search
@@ -37,15 +37,17 @@ func installByInstaller(killSignalChan chan<- any, packagePath, destDir string)
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
// Find the installer file
|
||||
var installerPath string
|
||||
for _, file := range reader.File {
|
||||
cleanName := filepath.Clean(file.Name)
|
||||
if strings.HasPrefix(cleanName, "..") || filepath.IsAbs(cleanName) {
|
||||
continue
|
||||
}
|
||||
if file.FileInfo().IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Extract file
|
||||
path := filepath.Join(tempDir, file.Name)
|
||||
path := filepath.Join(tempDir, cleanName)
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
|
||||
return err
|
||||
@@ -101,7 +103,11 @@ func installByPortable(killSignalChan chan<- any, packagePath, destDir string) e
|
||||
defer reader.Close()
|
||||
|
||||
for _, file := range reader.File {
|
||||
path := filepath.Join(destDir, file.Name)
|
||||
cleanName := filepath.Clean(file.Name)
|
||||
if strings.HasPrefix(cleanName, "..") || filepath.IsAbs(cleanName) {
|
||||
continue
|
||||
}
|
||||
path := filepath.Join(destDir, cleanName)
|
||||
|
||||
if file.FileInfo().IsDir() {
|
||||
os.MkdirAll(path, file.Mode())
|
||||
|
||||
@@ -282,19 +282,15 @@ func countArchiveFiles(archivePath string, password string) (int, error) {
|
||||
|
||||
// extractFile handles extracting a single file from an archive
|
||||
func extractFile(ctx context.Context, fileInfo archives.FileInfo, destDir string) error {
|
||||
// Skip directories, they will be created when extracting files
|
||||
if fileInfo.IsDir() {
|
||||
destPath := filepath.Join(destDir, fileInfo.NameInArchive)
|
||||
return os.MkdirAll(destPath, fileInfo.Mode())
|
||||
}
|
||||
|
||||
// Sanitize the path to prevent path traversal attacks
|
||||
cleanPath := filepath.Clean(fileInfo.NameInArchive)
|
||||
if strings.HasPrefix(cleanPath, "..") || filepath.IsAbs(cleanPath) {
|
||||
// Skip files with suspicious paths
|
||||
return nil
|
||||
}
|
||||
|
||||
if fileInfo.IsDir() {
|
||||
return os.MkdirAll(filepath.Join(destDir, cleanPath), fileInfo.Mode())
|
||||
}
|
||||
|
||||
destPath := filepath.Join(destDir, cleanPath)
|
||||
|
||||
// Create parent directories
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/bodgit/sevenzip"
|
||||
)
|
||||
@@ -43,7 +44,11 @@ func extractSevenZipMultiPart(firstPartPath string, destDir string, password str
|
||||
// Extract files with progress tracking
|
||||
extractedFiles := 0
|
||||
for _, f := range reader.File {
|
||||
destPath := filepath.Join(destDir, f.Name)
|
||||
cleanName := filepath.Clean(f.Name)
|
||||
if strings.HasPrefix(cleanName, "..") || filepath.IsAbs(cleanName) {
|
||||
continue
|
||||
}
|
||||
destPath := filepath.Join(destDir, cleanName)
|
||||
|
||||
if f.FileInfo().IsDir() {
|
||||
if err := os.MkdirAll(destPath, f.Mode()); err != nil {
|
||||
@@ -52,7 +57,6 @@ func extractSevenZipMultiPart(firstPartPath string, destDir string, password str
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure parent directory exists
|
||||
if err := os.MkdirAll(filepath.Dir(destPath), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user