From 8a327110ee89c2ce0875fda5734868c635ca0077 Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Sun, 16 Aug 2026 13:17:03 +0200 Subject: [PATCH] prevent security warning about "Zip Slip" in RPI camera downloader (#6096) --- .../rpicamera/mtxrpicamdownloader/main.go | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/internal/staticsources/rpicamera/mtxrpicamdownloader/main.go b/internal/staticsources/rpicamera/mtxrpicamdownloader/main.go index d311ffbb..801a837d 100644 --- a/internal/staticsources/rpicamera/mtxrpicamdownloader/main.go +++ b/internal/staticsources/rpicamera/mtxrpicamdownloader/main.go @@ -13,6 +13,7 @@ import ( "log" "net/http" "os" + "path/filepath" "strings" ) @@ -20,12 +21,36 @@ const ( maxInboundRPICameraSize = 10 * 1024 * 1024 ) +func absolutePathInside(base string, candidate string) (string, error) { + baseAbs, err := filepath.Abs(filepath.Clean(base)) + if err != nil { + return "", err + } + + candidateAbs, err := filepath.Abs(filepath.Clean(candidate)) + if err != nil { + return "", err + } + + rel, err := filepath.Rel(baseAbs, candidateAbs) + if err != nil { + return "", err + } + + if rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) { + return "", fmt.Errorf("path escapes base directory") + } + + return candidateAbs, nil +} + func dumpTar(src io.Reader) error { uncompressed, err := gzip.NewReader(src) if err != nil { return err } + baseDir := "." tr := tar.NewReader(uncompressed) for { @@ -38,16 +63,22 @@ func dumpTar(src io.Reader) error { return err } + var targetPath string + targetPath, err = absolutePathInside(baseDir, filepath.Join(baseDir, header.Name)) + if err != nil { + return fmt.Errorf("invalid archive entry: %s", header.Name) + } + switch header.Typeflag { case tar.TypeDir: - err = os.Mkdir(header.Name, header.FileInfo().Mode()) + err = os.Mkdir(targetPath, header.FileInfo().Mode()) if err != nil { return err } case tar.TypeReg: var f *os.File - f, err = os.OpenFile(header.Name, os.O_WRONLY|os.O_CREATE, header.FileInfo().Mode()) + f, err = os.OpenFile(targetPath, os.O_WRONLY|os.O_CREATE, header.FileInfo().Mode()) if err != nil { return err }