Documentation
¶
Overview ¶
Package pathvalidation validates that a file path is safe to write within a project directory. This is a security-critical package — it prevents any write operation from escaping the intended project boundary.
Threat model (from spec):
- Relative traversal: ../../etc/passwd
- Embedded traversal: internal/../../outside/file.go
- OS-specific separators: backslash on Windows (..\..\)
- Encoding tricks: URL-encoded or Unicode sequences
- Symlinks: a valid-looking relative path that resolves outside the project via a symlink in the directory tree
OWASP guidance applied here:
- Normalize before validating (filepath.Clean)
- Resolve symlinks before containment check (filepath.EvalSymlinks)
- Reject, never sanitize
- Prefer allow-list reasoning: only paths that pass every gate are accepted
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ValidatePath ¶
ValidatePath checks whether path is a safe relative path that, when joined with projectRoot, remains inside the project directory tree.
Returns nil when the path is safe. Returns a descriptive error otherwise. This function never writes or creates anything on disk.
Algorithm (spec §Contracts/Algorithm):
- Reject empty paths.
- Reject absolute paths: strings.HasPrefix(path, "/") catches Unix-style absolute paths on all platforms (including Windows, where filepath.IsAbs returns false for "/etc/passwd" without a drive letter). Also reject if the path contains ":" (Windows drive letter, e.g. "C:\...").
- Call filepath.Clean to normalize separators and resolve "." segments.
- Reject if any path component is ".." after cleaning.
- Resolve the full absolute path: abs = filepath.Join(projectRoot, cleaned).
- Call filepath.EvalSymlinks on abs; if the target does not exist yet, evaluate the longest existing prefix instead.
- Verify the resolved path starts with projectRoot. Reject if not.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.