Use when an org role acts as path validator and must stop path traversal by checking any user-influenced file path resolves inside its intended base directory. Covers canonicalize-then-prefix-check, decoding before validation, symlink escapes, null-byte tricks, filename allowlists and Windows vs POSIX differences.
21 stars
0 votes
0 copies
1 view
Added September 22, 2026
ai-agentsrustphpgitapisecurity
Works with
cli
api
Security analysis
B75/100
criticalAccesses sensitive system or user directories
Installs into .claude/skills of the current project.
Are you the author of Path Validator?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/monoes-path-validator)
---
name: path-validator
description: "Use when an org role acts as path validator and must stop path traversal by checking any user-influenced file path resolves inside its intended base directory. Covers canonicalize-then-prefix-check, decoding before validation, symlink escapes, null-byte tricks, filename allowlists and Windows vs POSIX differences."
tags: ["security","audit","api"]
tools: ["monograph_query","monograph_context","monograph_impact"]
license: Apache-2.0
source: https://github.com/monoes/monomind
---
# Path Validator — Best Practices
## Focus
Guards filesystem access from path traversal and injection — ensures any user-influenced path resolves inside its intended base directory before it's ever opened, read, or written.
## Best practices
- Avoid passing user-supplied input to filesystem APIs at all where possible — offer a fixed set of choices (an ID mapped server-side to a path) instead of a raw path
- When a path must be accepted, canonicalize it first: resolve `.`, `..`, and symlinks to get the true final path before making any decision
- Validate *after* decoding, never before — attackers stack multiple encoding layers (`%2e%2e/`, double-encoding, unicode variants) specifically to slip past pre-decode filters
- After canonicalizing, verify the resolved path starts with the expected base directory (prefix check on the canonical form, not the raw string)
- Restrict accepted filenames/extensions to an explicit allowlist (alphanumeric plus a small safe character set) rather than trying to blocklist dangerous sequences
- Treat every uploaded filename as untrusted — never use the client-supplied filename directly for storage; generate or map it server-side
- Apply the same canonicalize-then-prefix-check logic on every OS you deploy to — Windows path semantics (`\`, drive letters, alternate streams) differ from POSIX and need their own checks
## Common pitfalls
- Blocklisting `../` as a raw string match — trivially defeated by encoding, mixed separators, or double-encoded sequences
- Doing the base-directory prefix check on the raw input instead of the canonicalized path, so `../../etc/passwd` slips through pre-resolution
- Forgetting symlinks: a filename can be "inside" the base directory while a symlink underneath it points somewhere else entirely
- Validating the extension but not the full path, letting `evil.php%00.jpg`-style null-byte or double-extension tricks through
- Assuming validation done once at upload time still holds when the file is later moved, renamed, or accessed via a different code path
## Tools & techniques
- Canonicalization APIs (`realpath`, `Path.resolve`/`Path.normalize` + prefix check, `os.path.realpath`) as the mandatory first step before any comparison
- Explicit base-directory containment check: canonical path must start with canonical base directory + separator, not just a substring match
- Filename allowlist regex (e.g. `^[a-zA-Z0-9._-]+$`) combined with a maximum length limit
- Chroot/jail, containerized filesystem mounts, or scoped storage buckets as a second layer of defense beyond application-level checks
- Automated test cases covering `../`, encoded traversal, symlink escapes, and null-byte injection for every path-accepting endpoint