Path traversal lets attackers read files outside the intended directory by manipulating file path inputs with ../ sequences. It has been in the OWASP Top 10 for over two decades. It still appears in production applications in 2026 because developers normalize paths inconsistently, framework defaults vary, and the attack surface grows every time a new file-handling feature is added.
Analysis Briefing
- Topic: Path traversal vulnerability mechanics and prevention in modern web applications
- Analyst: Mike D (@MrComputerScience)
- Context: Sparked by a question from Claude Sonnet 4.6
- Source: Pithy Cyborg | Pithy Security
- Key Question: How does a
../in a filename let attackers read your server’s password file?
How Path Traversal Works and Why the Obvious Fix Fails
A web application that serves files based on user input constructs a file path from a base directory and the user-supplied filename. A request for /files?name=report.pdf constructs the path /var/app/uploads/report.pdf and serves that file. A request for /files?name=../../etc/passwd constructs the path /var/app/uploads/../../etc/passwd, which resolves to /etc/passwd.
The obvious fix is filtering ../ from the input. This fails for several reasons. URL encoding represents ../ as %2e%2e%2f. Double URL encoding represents it as %252e%252e%252f. Some applications decode URL encoding once and send the decoded string to the file system, which decodes it again. The filter sees %2e%2e%2f and allows it through. The file system sees ../.
Unicode normalization creates a second bypass. The Unicode character U+FF0E is a fullwidth full stop that looks identical to a period and normalizes to . after Unicode normalization. Path inputs containing fullwidth periods pass ASCII-based filters and resolve to traversal sequences after normalization.
Windows path separators add a third bypass on Windows systems. Both / and \ are valid path separators on Windows. Filters that block / traversal sequences miss \ equivalents. A request for ..\..\..\windows\system32\ traverses the same path on Windows with different separators.
Where Path Traversal Appears in Modern Applications
File download endpoints are the most common location. Any feature that serves files from disk based on a user-supplied filename or path parameter is a path traversal candidate. Document management systems, file sharing features, and export functions that write and serve temporary files all fit this pattern.
File upload endpoints have a second-order path traversal risk. Applications that use the user-supplied filename to determine where to store the uploaded file are vulnerable to attackers who submit filenames containing traversal sequences. A file uploaded as ../../app/config/settings.py may overwrite application configuration if the upload handler does not normalize the filename before constructing the storage path.
Template and configuration loading is a less obvious surface. Applications that load template files or configuration based on request parameters, common in multi-tenant applications that serve different themes or configurations per customer, are vulnerable if the parameter value feeds into a file path without normalization.
Log file viewers and diagnostic endpoints that expose server files based on path parameters are a final high-risk category. These features are often added during development as debugging aids and never removed or secured.
The Fix That Actually Works
The correct fix is not input filtering. It is path canonicalization followed by prefix verification.
import os
def safe_file_path(base_dir: str, user_input: str) -> str:
# Resolve the full absolute path, resolving all .. and symlinks
requested_path = os.path.realpath(
os.path.join(base_dir, user_input)
)
# Verify the resolved path starts with the base directory
real_base = os.path.realpath(base_dir)
if not requested_path.startswith(real_base + os.sep):
raise ValueError("Path traversal attempt detected")
return requested_path
os.path.realpath() resolves all ../ sequences, symlinks, and encoding variations to the canonical absolute path. The prefix check verifies that the resolved path is within the intended directory. This approach handles every encoding and normalization bypass because it operates on the canonical path, not the raw input.
The SSRF vulnerabilities in cloud environments that affect server-side URL handling follow the same pattern as path traversal: user input reaches a system call without sufficient validation of where it points.
What This Means For You
- Use path canonicalization and prefix verification, not input filtering. Filters fail against encoding bypasses. Canonicalization followed by a prefix check is the pattern that holds against all bypass techniques.
- Audit every file-serving endpoint in your application for user-controlled path components. Any endpoint where a request parameter feeds into a file system operation is a path traversal candidate until proven otherwise.
- Use randomized filenames for uploads instead of user-supplied ones. A UUID-based filename eliminates path traversal in the upload handler entirely. Store the original filename as metadata, not as the storage path.
- Add path traversal test cases to your security regression suite. Test with
../,%2e%2e%2f,%252e%252e%252f, and Unicode fullwidth period variants. If any reach the file system without raising an exception, the fix is incomplete.
Enjoyed this deep dive? Join my inner circle:
- Pithy Cyborg → AI news made simple without hype.
- Pithy Security → Stay ahead of cybersecurity threats.
