From 152f8a35c55ae03f2a6858df205081403b4837d1 Mon Sep 17 00:00:00 2001 From: Don Browne Date: Thu, 6 Nov 2025 17:19:07 +0000 Subject: [PATCH 1/6] Do not convert volume target path to Windows style Since we deal with Linux containers, the volume target path should always be a Unix style path, even on Windows. Prior to this, the code would convert the target path to a Windows style path on Windows hosts due to the use of filepath.Clean. This PR changes the code to use path.Clean for the target instead, which always produces a Unix style path. Pre-existing validation ensures that the user cannot pass Windows style paths as input. --- pkg/permissions/profile.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/permissions/profile.go b/pkg/permissions/profile.go index 30a83516c..d3e9198ac 100644 --- a/pkg/permissions/profile.go +++ b/pkg/permissions/profile.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "os" + pkgpath "path" "path/filepath" "regexp" "strings" @@ -198,11 +199,6 @@ func isWindowsPath(path string) bool { return false } -// cleanPath cleans a path using filepath.Clean -func cleanPath(path string) string { - return filepath.Clean(path) -} - // validateResourceScheme checks if a resource URI scheme is valid func validateResourceScheme(scheme string) bool { return regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]*$`).MatchString(scheme) @@ -299,8 +295,10 @@ func parseResourceURI(declaration string) (source, target string, err error) { } // Clean paths - cleanedResource := cleanPath(resourceName) - cleanedTarget := cleanPath(containerPath) + cleanedResource := filepath.Clean(resourceName) + // For the target, we explicitly use path.Clean so that we do not convert + // Unix style paths into Windows style paths on Windows hosts + cleanedTarget := pkgpath.Clean(containerPath) return scheme + "://" + cleanedResource, cleanedTarget, nil } @@ -324,7 +322,7 @@ func parseWindowsPath(declaration string, colonPositions []int) (source, target if err := validatePath(declaration); err != nil { return "", "", err } - cleanedPath := cleanPath(declaration) + cleanedPath := filepath.Clean(declaration) return cleanedPath, cleanedPath, nil } @@ -346,8 +344,8 @@ func parseWindowsPath(declaration string, colonPositions []int) (source, target return "", "", err } - cleanedSource := cleanPath(hostPath) - cleanedTarget := cleanPath(containerPath) + cleanedSource := filepath.Clean(hostPath) + cleanedTarget := filepath.Clean(containerPath) return cleanedSource, cleanedTarget, nil } @@ -381,8 +379,9 @@ func parseHostContainerPath(declaration string, colonPositions []int) (source, t return "", "", err } - cleanedSource := cleanPath(hostPath) - cleanedTarget := cleanPath(containerPath) + cleanedSource := filepath.Clean(hostPath) + // See comment above about using path.Clean instead of filepath.Clean. + cleanedTarget := pkgpath.Clean(containerPath) return cleanedSource, cleanedTarget, nil } @@ -401,7 +400,8 @@ func parseSinglePath(declaration string) (source, target string, err error) { return "", "", err } - cleanedPath := cleanPath(declaration) + // See comment above about using path.Clean instead of filepath.Clean. + cleanedPath := pkgpath.Clean(declaration) return cleanedPath, cleanedPath, nil } From f4c85de40e9cdd4e19bf201a110a3a1425502a5a Mon Sep 17 00:00:00 2001 From: Don Browne Date: Thu, 6 Nov 2025 17:55:26 +0000 Subject: [PATCH 2/6] Missed one... --- pkg/permissions/profile.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/permissions/profile.go b/pkg/permissions/profile.go index d3e9198ac..6e891bfe1 100644 --- a/pkg/permissions/profile.go +++ b/pkg/permissions/profile.go @@ -345,7 +345,8 @@ func parseWindowsPath(declaration string, colonPositions []int) (source, target } cleanedSource := filepath.Clean(hostPath) - cleanedTarget := filepath.Clean(containerPath) + // See comment above about using path.Clean instead of filepath.Clean. + cleanedTarget := pkgpath.Clean(containerPath) return cleanedSource, cleanedTarget, nil } From d6f90f8de84588eb8dc31f74095c037370cc283d Mon Sep 17 00:00:00 2001 From: Don Browne Date: Thu, 6 Nov 2025 18:33:47 +0000 Subject: [PATCH 3/6] Implement tilde expansion for Windows --- pkg/container/docker/client.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/pkg/container/docker/client.go b/pkg/container/docker/client.go index a5b7f7dd7..6d104ce53 100644 --- a/pkg/container/docker/client.go +++ b/pkg/container/docker/client.go @@ -10,6 +10,7 @@ import ( "io" "os" "path/filepath" + rt "runtime" "slices" "strconv" "strings" @@ -756,15 +757,23 @@ func convertRelativePathToAbsolute(source string, mountDecl permissions.MountDec return source, true } - // Get the current working directory - cwd, err := os.Getwd() - if err != nil { - logger.Warnf("Warning: Failed to get current working directory: %v", err) - return "", false + var basePath string + var err error + // Special case for Windows: expand ~ to user profile directory. + if rt.GOOS == "windows" && strings.HasPrefix(source, "~") { + basePath = os.Getenv("USERPROFILE") + source = strings.Replace(source, "~", basePath, 1) + } else { + // Otherwise: Get the current working directory + basePath, err = os.Getwd() + if err != nil { + logger.Warnf("Warning: Failed to get current working directory: %v", err) + return "", false + } } // Convert relative path to absolute path - absPath := filepath.Join(cwd, source) + absPath := filepath.Join(basePath, source) logger.Infof("Converting relative path to absolute: %s -> %s", mountDecl, absPath) return absPath, true } From 97e36e7fddb4275967e90e073e27e1a3dc072507 Mon Sep 17 00:00:00 2001 From: Don Browne Date: Thu, 6 Nov 2025 18:41:45 +0000 Subject: [PATCH 4/6] cleanup relative path conversion --- pkg/container/docker/client.go | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/pkg/container/docker/client.go b/pkg/container/docker/client.go index 6d104ce53..593800c7b 100644 --- a/pkg/container/docker/client.go +++ b/pkg/container/docker/client.go @@ -757,23 +757,18 @@ func convertRelativePathToAbsolute(source string, mountDecl permissions.MountDec return source, true } - var basePath string - var err error // Special case for Windows: expand ~ to user profile directory. if rt.GOOS == "windows" && strings.HasPrefix(source, "~") { - basePath = os.Getenv("USERPROFILE") - source = strings.Replace(source, "~", basePath, 1) - } else { - // Otherwise: Get the current working directory - basePath, err = os.Getwd() - if err != nil { - logger.Warnf("Warning: Failed to get current working directory: %v", err) - return "", false - } + homeDir := os.Getenv("USERPROFILE") + source = strings.Replace(source, "~", homeDir, 1) } - // Convert relative path to absolute path - absPath := filepath.Join(basePath, source) + absPath, err := filepath.Abs(source) + if err != nil { + logger.Warnf("Warning: Failed to convert to absolute path: %s (%v)", mountDecl, err) + return "", false + } + logger.Infof("Converting relative path to absolute: %s -> %s", mountDecl, absPath) return absPath, true } From a04fc769f27f370c1b32866f6d4df392702d03f1 Mon Sep 17 00:00:00 2001 From: Don Browne Date: Thu, 6 Nov 2025 18:49:18 +0000 Subject: [PATCH 5/6] lint fix --- pkg/container/docker/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/container/docker/client.go b/pkg/container/docker/client.go index 593800c7b..c3a51c1a3 100644 --- a/pkg/container/docker/client.go +++ b/pkg/container/docker/client.go @@ -768,7 +768,7 @@ func convertRelativePathToAbsolute(source string, mountDecl permissions.MountDec logger.Warnf("Warning: Failed to convert to absolute path: %s (%v)", mountDecl, err) return "", false } - + logger.Infof("Converting relative path to absolute: %s -> %s", mountDecl, absPath) return absPath, true } From db5cbe8aa8288a53f53c409ff221c21a5e67c1e4 Mon Sep 17 00:00:00 2001 From: Don Browne Date: Fri, 7 Nov 2025 09:24:55 +0000 Subject: [PATCH 6/6] PR feedback --- pkg/permissions/profile.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/permissions/profile.go b/pkg/permissions/profile.go index 6e891bfe1..4e54345a6 100644 --- a/pkg/permissions/profile.go +++ b/pkg/permissions/profile.go @@ -401,8 +401,8 @@ func parseSinglePath(declaration string) (source, target string, err error) { return "", "", err } - // See comment above about using path.Clean instead of filepath.Clean. - cleanedPath := pkgpath.Clean(declaration) + // Single path should always be converted to OS-specific cleaned path. + cleanedPath := filepath.Clean(declaration) return cleanedPath, cleanedPath, nil }