mirror of
https://github.com/traefik/traefik.git
synced 2025-08-06 06:37:09 +02:00
Fix client arbitrary file access during archive extraction zipslip
This commit is contained in:
parent
b2b4b66b08
commit
5ef853a0c5
@ -240,6 +240,8 @@ func (c *Client) Unzip(pName, pVersion string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unzip as a generic archive if the module unzip fails.
|
||||
// This is useful for plugins that have vendor directories or other structures.
|
||||
return c.unzipArchive(pName, pVersion)
|
||||
}
|
||||
|
||||
@ -280,24 +282,48 @@ func unzipFile(f *zipa.File, dest string) error {
|
||||
|
||||
defer func() { _ = rc.Close() }()
|
||||
|
||||
// Split to discard the first part of the path, which is [organization]-[project]-[release commit sha1] when the archive is a Yaegi go plugin with vendoring.
|
||||
pathParts := strings.SplitN(f.Name, "/", 2)
|
||||
p := filepath.Join(dest, pathParts[1])
|
||||
if len(pathParts) < 2 {
|
||||
return fmt.Errorf("no root directory: %s", f.Name)
|
||||
}
|
||||
|
||||
// Validate and sanitize the file path.
|
||||
cleanName := filepath.Clean(pathParts[1])
|
||||
if strings.Contains(cleanName, "..") {
|
||||
return fmt.Errorf("invalid file path in archive: %s", f.Name)
|
||||
}
|
||||
|
||||
filePath := filepath.Join(dest, cleanName)
|
||||
absFilePath, err := filepath.Abs(filePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving file path: %w", err)
|
||||
}
|
||||
|
||||
absDest, err := filepath.Abs(dest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolving destination directory: %w", err)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(absFilePath, absDest) {
|
||||
return fmt.Errorf("file path escapes destination directory: %s", absFilePath)
|
||||
}
|
||||
|
||||
if f.FileInfo().IsDir() {
|
||||
err = os.MkdirAll(p, f.Mode())
|
||||
err = os.MkdirAll(filePath, f.Mode())
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create archive directory %s: %w", p, err)
|
||||
return fmt.Errorf("unable to create archive directory %s: %w", filePath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(p), 0o750)
|
||||
err = os.MkdirAll(filepath.Dir(filePath), 0o750)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create archive directory %s for file %s: %w", filepath.Dir(p), p, err)
|
||||
return fmt.Errorf("unable to create archive directory %s for file %s: %w", filepath.Dir(filePath), filePath, err)
|
||||
}
|
||||
|
||||
elt, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
elt, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user