Skip to content

CWE-22: Path Traversal

Overview

Path Traversal (Directory Traversal) occurs when an application uses user-supplied input to construct file paths without proper validation, allowing attackers to access files outside the intended directory.

OWASP Classification

A01:2025 - Broken Access Control

Risk

High: Can lead to unauthorized file access, source code disclosure, credential theft, or remote code execution if combined with file upload.

Relationship to Other CWEs

CWE-22 vs CWE-73 vs CWE-35:

  • CWE-22 (This page): Focuses specifically on path traversal sequences (../, ..\) that allow escaping intended directories. Use this guidance when findings mention "directory traversal" or "dot-dot-slash".
  • CWE-73 (External Control of File Name or Path): Broader category covering any user control over file paths, including both traversal attacks AND choosing arbitrary files within allowed directories. If your scan finding is CWE-73, check if it involves traversal sequences (also apply CWE-22 guidance) or just file selection.
  • CWE-35 (Path Equivalence): Focuses on equivalent representations of the same path (/path vs /path/ vs //path) bypassing validation. Less common in findings; mainly relevant if your validation uses string comparison without canonicalization.

Remediation overlap: All three benefit from canonicalization and allowlisting. CWE-22 and CWE-73 share most remediation steps.

Common Attack Patterns

  • ../../../etc/passwd (Unix/Linux)
  • ..\..\..\..\windows\system32\config\sam (Windows)
  • URL encoding: %2e%2e%2f, %2e%2e\
  • Double encoding: %252e%252e%252f
  • Absolute paths: /etc/passwd, C:\windows\system.ini

Remediation Steps

Core principle: Never allow untrusted input to directly control filesystem paths; canonicalize and enforce containment within an allowlisted root.

Trace the Data Path

Analyze how untrusted data reaches file operations:

  • Source: Identify where file path data enters (user input, external files, databases, network requests)
  • Path Construction: Look for string concatenation with / or \
  • Sink: Locate file operation (open(), File(), readFile(), etc.)
  • Missing Validation: Check for canonicalization or containment checks

Use Indirect References (Primary Defense)

Never use untrusted data directly as file paths. Use indirect references:

  • Map to internal IDs: User provides ID/name, system maps to actual path
  • Lookup from allowlist/database: Maintain allowed files in database
  • Hide real paths: Users never see or control actual file paths
  • Example: User requests report_id=123, system maps to /var/reports/2024/report_123.pdf

Why this works: Users cannot manipulate paths they never see or control.

Validate Against Allowlist

If direct file references are unavoidable:

  • Define allowed files/directories: Maintain explicit list of permitted paths
  • Exact matching: Exact matching for file identifiers or filenames (not raw user-supplied paths)
  • Reject unlisted items: Reject any input not on the allowlist
  • No pattern matching: Don't use wildcards or regex for allowlisting paths

Canonicalize and Validate Path Containment

Resolve paths to their canonical form and verify containment:

Canonicalization process: 1. Resolve symlinks and relative path segments (.., .) 2. Convert to absolute canonical path 3. Normalize path separators 4. Verify resolved path starts with allowed base directory 5. Check BEFORE opening the file

Example validation:

base_dir = "/var/www/uploads"
user_path = canonicalize(join(base_dir, user_input))
if not user_path.starts_with(base_dir):
    reject()

Use Secure Path Manipulation APIs

Use language-native path APIs that prevent traversal:

  • Never concatenate strings to build file paths
  • Use path joining functions that normalize separators (path.join(), Path.Combine())
  • Reject dangerous patterns: Reject paths containing .., absolute paths, or null bytes
  • Use filesystem APIs: Leverage built-in path validation in your language

Test with Path Traversal Payloads

Verify your fixes with attack patterns:

  • ../../../etc/passwd (Unix/Linux)
  • ..\..\..\..\windows\system32\config\sam (Windows)
  • URL encoding: %2e%2e%2f, %2e%2e\
  • Double encoding: %252e%252e%252f
  • Absolute paths: /etc/passwd, C:\windows\system.ini
  • Null byte injection: allowed.txt%00../../etc/passwd
  • Mixed separators: ..././..././etc/passwd
  • Ensure legitimate file access still works correctly

Language-Specific Guidance

For detailed, language-specific examples and framework-specific patterns:

  • C# - Path.Combine, Path.GetFullPath for secure file access
  • Java - File, Path, Files API with canonical path validation
  • JavaScript/Node.JS - fs, path modules, Express static with path resolution

Dynamic Scan Guidance

For guidance on remediating this CWE when detected by dynamic (DAST) scanners:

Additional Resources