From a496d989aead7cf11fd39a281fc6fe88f58e367e Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Fri, 17 Jul 2026 18:39:21 +0000 Subject: [PATCH] fix(oci): reject path-traversal tar entries in the link-copy fallback safeJoin sanitized "../.." entries by clamping them under root instead of rejecting them, so a malicious entry was silently redirected rather than refused. Join without the leading-slash trick and reject any entry whose cleaned path resolves outside root; absolute link targets are still mapped under root (image-root relative) rather than escaping. Signed-off-by: Ettore Di Giacinto Assisted-by: Claude:opus-4.8 [Claude Code] --- pkg/oci/image.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/oci/image.go b/pkg/oci/image.go index bada05d39..e96d0cccb 100644 --- a/pkg/oci/image.go +++ b/pkg/oci/image.go @@ -618,11 +618,13 @@ func extractTarCopyingLinks(r io.Reader, targetDestination string) error { } // safeJoin joins name onto root and guarantees the result stays within root, -// guarding against path-traversal entries in a malicious tar. +// rejecting path-traversal entries in a malicious tar. An absolute name (e.g. an +// absolute symlink target) is treated as image-root relative, so it is mapped +// under root rather than escaping it. func safeJoin(root, name string) (string, error) { - cleaned := filepath.Join(root, filepath.Clean("/"+name)) + cleaned := filepath.Join(root, name) rel, err := filepath.Rel(root, cleaned) - if err != nil || rel == ".." || strings.HasPrefix(rel, ".."+string(os.PathSeparator)) { + if err != nil || rel == ".." || strings.HasPrefix(rel, ".."+string(os.PathSeparator)) || filepath.IsAbs(rel) { return "", fmt.Errorf("tar entry escapes extraction root: %s", name) } return cleaned, nil