adr/001-path-traversal-protection.md
Date: 2025-01-21
Accepted
The cheat tool allows users to create, edit, and remove cheatsheets using commands like:
cheat --edit <name>cheat --rm <name>Without validation, a user could potentially provide malicious names like:
../../../etc/passwd (directory traversal)/etc/passwd (absolute path)~/.ssh/authorized_keys (home directory expansion)While cheat is a local tool run by the user themselves (not a network service), path traversal could still lead to:
We implemented input validation for cheatsheet names to prevent directory traversal attacks. The validation rejects names that:
.. (parent directory references)/ on Unix)~ (home directory expansion). (hidden files - these are not displayed by cheat)The validation is performed at the application layer before any file operations occur.
The validation is implemented in internal/sheet/validate.go:
func Validate(name string) error {
// Reject empty names
if name == "" {
return fmt.Errorf("cheatsheet name cannot be empty")
}
// Reject names containing directory traversal
if strings.Contains(name, "..") {
return fmt.Errorf("cheatsheet name cannot contain '..'")
}
// Reject absolute paths
if filepath.IsAbs(name) {
return fmt.Errorf("cheatsheet name cannot be an absolute path")
}
// Reject names that start with ~ (home directory expansion)
if strings.HasPrefix(name, "~") {
return fmt.Errorf("cheatsheet name cannot start with '~'")
}
// Reject hidden files (files that start with a dot)
filename := filepath.Base(name)
if strings.HasPrefix(filename, ".") {
return fmt.Errorf("cheatsheet name cannot start with '.' (hidden files are not supported)")
}
return nil
}
The validation is called in:
cmd/cheat/cmd_edit.go - before creating or editing a cheatsheetcmd/cheat/cmd_remove.go - before removing a cheatsheetThe following patterns are explicitly allowed:
docker, gitdocker/compose, lang/go/slice./mysheet.. in cheatsheet names even if legitimatefilepath.IsAbs() which handles platform differences (Windows vs Unix)cheat is a local command-line tool, not a network service. The primary threats are:
cheat with crafted arguments../~ to home directoryComprehensive tests ensure the validation works correctly:
internal/sheet/validate_test.go) verify the validation logicExample test cases:
# These are blocked:
cheat --edit "../../../etc/passwd"
cheat --edit "/etc/passwd"
cheat --edit "~/.ssh/config"
cheat --rm ".."
# These are allowed:
cheat --edit "docker"
cheat --edit "docker/compose"
cheat --edit "./local"
Path resolution and verification: Resolve the final path and check if it's within the cheatpath
Chroot/sandbox: Run file operations in a restricted environment
Filename allowlist: Only allow alphanumeric characters and specific symbols