From c834a9835f2603f0502d83e54f4a92e2fb5c26f0 Mon Sep 17 00:00:00 2001 From: Martin Brodeur <63083086+brodmart@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:32:39 -0400 Subject: [PATCH] fix: prevent zip-slip path traversal in OCI layer extraction Add a prefix check in ExtractFile() immediately after computing the extraction path to ensure tar entries cannot escape the root directory. Also guard absolute symlink targets in TypeSymlink entries. CVSS 3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 CRITICAL CWE-22: Improper Limitation of a Pathname to a Restricted Directory --- pkg/util/fs_util.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index 9b641f1ff3..9496cf5002 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -396,6 +396,10 @@ func UnTar(r io.Reader, dest string) ([]string, error) { func ExtractFile(dest string, hdr *tar.Header, cleanedName string, tr io.Reader) error { path := filepath.Join(dest, cleanedName) + cleanRoot := filepath.Clean(dest) + string(filepath.Separator) + if !strings.HasPrefix(filepath.Clean(path)+string(filepath.Separator), cleanRoot) { + return fmt.Errorf("path traversal detected in tar entry %q escapes root", hdr.Name) + } base := filepath.Base(path) dir := filepath.Dir(path) mode := hdr.FileInfo().Mode() @@ -501,6 +505,13 @@ func ExtractFile(dest string, hdr *tar.Header, cleanedName string, tr io.Reader) return errors.Wrapf(err, "error removing %s to make way for new symlink", hdr.Name) } } + // Guard: absolute symlink targets must resolve within dest + if filepath.IsAbs(hdr.Linkname) { + cleanTarget := filepath.Clean(hdr.Linkname) + string(filepath.Separator) + if !strings.HasPrefix(cleanTarget, cleanRoot) { + return fmt.Errorf("path traversal detected in symlink target %q escapes root", hdr.Linkname) + } + } if err := filesystem.FS.Symlink(hdr.Linkname, path); err != nil { return err }