From ca747c54d9f772257b970115fdcc01ef358f91a5 Mon Sep 17 00:00:00 2001 From: immanuwell Date: Wed, 27 May 2026 11:38:58 +0400 Subject: [PATCH] fix: reject parent directory template locators Signed-off-by: immanuwell --- pkg/limatmpl/abs.go | 9 ++++++++- pkg/limatmpl/abs_test.go | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/pkg/limatmpl/abs.go b/pkg/limatmpl/abs.go index 5dc97495e37..c0731ca165d 100644 --- a/pkg/limatmpl/abs.go +++ b/pkg/limatmpl/abs.go @@ -11,6 +11,7 @@ import ( "path" "path/filepath" "runtime" + "slices" "strings" "github.com/lima-vm/lima/v2/pkg/localpathutil" @@ -126,7 +127,7 @@ func absPath(locator, basePath string) (string, error) { return "", errors.New("basePath is empty") case basePath == "-": return "", errors.New("can't use relative paths when reading template from STDIN") - case strings.Contains(locator, "../"): + case containsParentDir(locator): return "", fmt.Errorf("relative locator path %q must not contain '../' segments", locator) case volumeLen != 0: return "", fmt.Errorf("relative locator path %q must not include a volume name", locator) @@ -146,3 +147,9 @@ func absPath(locator, basePath string) (string, error) { } return withVolume(locator) } + +func containsParentDir(locator string) bool { + return slices.Contains(strings.FieldsFunc(locator, func(r rune) bool { + return r == '/' || (runtime.GOOS == "windows" && r == '\\') + }), "..") +} diff --git a/pkg/limatmpl/abs_test.go b/pkg/limatmpl/abs_test.go index df4c8c40db1..5d65592033d 100644 --- a/pkg/limatmpl/abs_test.go +++ b/pkg/limatmpl/abs_test.go @@ -249,6 +249,11 @@ func TestAbsPath(t *testing.T) { assert.ErrorContains(t, err, "'../'") }) + t.Run("Relative parent directory locator must be underneath the basePath", func(t *testing.T) { + _, err = absPath("..", volume+"/root") + assert.ErrorContains(t, err, "'../'") + }) + t.Run("locator must not be empty", func(t *testing.T) { _, err = absPath("", "foo") assert.ErrorContains(t, err, "locator is empty")