package util import ( "path/filepath" "strings" ) // CleanRelative validates and cleans a workspace-relative path. // It rejects absolute paths and paths that escape the workspace root via "..". // Empty path and "." return ".". func CleanRelative(path string) (string, error) { if path == "" || path == "." { return ".", nil } // Reject absolute paths. if filepath.IsAbs(path) { return "", New(CodeBadRequest, "absolute paths are not allowed") } cleaned := filepath.Clean(path) // Reject paths that escape the workspace root. if cleaned == ".." || strings.HasPrefix(cleaned, ".."+string(filepath.Separator)) { return "", New(CodeBadRequest, "path escapes workspace root") } return cleaned, nil } // JoinClean joins base and elem after cleaning, returning a cleaned path. func JoinClean(base, elem string) string { return filepath.Clean(filepath.Join(base, elem)) }