Files
coding-agent/safepath.go
2026-04-17 11:12:45 +03:00

30 lines
760 B
Go

package main
import (
"fmt"
"path/filepath"
"strings"
)
// resolveSafe joins p onto root, cleans it, and confirms the result stays
// within root. Rejects absolute paths and anything that escapes via "..".
func resolveSafe(root, p string) (string, error) {
if p == "" {
return "", fmt.Errorf("empty path")
}
if filepath.IsAbs(p) {
return "", fmt.Errorf("absolute paths are not allowed: %s", p)
}
joined := filepath.Join(root, p)
cleaned := filepath.Clean(joined)
rel, err := filepath.Rel(root, cleaned)
if err != nil {
return "", fmt.Errorf("cannot resolve %q: %w", p, err)
}
if rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
return "", fmt.Errorf("path escapes project root: %s", p)
}
return cleaned, nil
}