Weakness reference
CWE-35

Path Traversal (Multiple Leading Dots)

Path traversal using multiple leading dots is a file access vulnerability where an attacker manipulates file paths using sequences like ....// or ..../ to…

01Summary

Path traversal using multiple leading dots is a file access vulnerability where an attacker manipulates file paths using sequences like ....// or ..../ to escape intended directory boundaries. Unlike the canonical ../ sequence, these variants may evade simple string-matching filters, allowing unauthorized access to files outside the intended directory.

02How It Happens

Applications often restrict file access to a specific directory by checking for and removing the ../ sequence. However, some filters only look for the exact two-dot pattern and don't account for variations like ....// (four dots followed by slashes) or ..../ (dots with mixed separators). When the application processes these sequences—either by stripping only the first occurrence, normalizing paths incompletely, or failing to recursively check—the remaining dots can still resolve to parent directories. The vulnerability is compounded when the application doesn't validate the final resolved path against an allowlist of permitted locations.

03Real-World Impact

An attacker exploiting this weakness can read sensitive files outside the intended directory, such as configuration files containing database credentials, private keys, or source code. In some cases, if the application also allows file writes, an attacker could overwrite critical files or inject malicious code. The impact ranges from information disclosure to complete system compromise, depending on file permissions and what files are accessible.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import os

def serve_file(user_input):
    base_dir = "/var/www/uploads"
    # Attempt to filter "../" but misses "..../"
    sanitized = user_input.replace("../", "")
    file_path = os.path.join(base_dir, sanitized)
    
    with open(file_path, "r") as f:
        return f.read()

# Attacker input: "....//....//etc/passwd"
# After replace: "....//....//etc/passwd" (unchanged)
# Resolves to: "/etc/passwd"

Why it's vulnerable:
The filter only removes the exact ../ sequence, leaving ....// intact. When the path is normalized by the OS, the four dots resolve to parent directory traversal, bypassing the filter.

Fixed pattern
import os

def serve_file(user_input):
    base_dir = "/var/www/uploads"
    # Resolve to absolute path and validate it stays within base_dir
    file_path = os.path.abspath(os.path.join(base_dir, user_input))
    
    if not file_path.startswith(os.path.abspath(base_dir)):
        raise ValueError("Access denied: path outside allowed directory")
    
    with open(file_path, "r") as f:
        return f.read()
Vulnerable pattern
<?php
$base_dir = "/var/www/uploads";
$user_input = $_GET['file'];

// Attempt to filter "../" but misses "..../"
$sanitized = str_replace("../", "", $user_input);
$file_path = $base_dir . "/" . $sanitized;

echo file_get_contents($file_path);
?>

Why it's vulnerable:
The str_replace() call removes only ../, leaving ....// untouched. The OS path resolution then interprets the dots as directory traversal, escaping the intended directory.

Fixed pattern
<?php
$base_dir = realpath("/var/www/uploads");
$user_input = $_GET['file'];

// Resolve to absolute path and validate containment
$file_path = realpath($base_dir . "/" . $user_input);

if ($file_path === false || strpos($file_path, $base_dir) !== 0) {
    die("Access denied: path outside allowed directory");
}

echo file_get_contents($file_path);
?>

05Prevention Checklist

Use absolute path resolution:
Call realpath() (PHP) or os.path.abspath() (Python) on the final path and verify it remains within the intended base directory.
Allowlist permitted files or directories:
Rather than blacklisting dangerous patterns, explicitly define which files or directories users may access.
Avoid string-based filtering:
Do not rely on str_replace() or regex to remove ../ sequences; attackers can use variants. Always validate the resolved path.
Canonicalize paths before validation:
Normalize the path to its simplest form before checking it against your allowlist.
Run with minimal file permissions:
Ensure the application process has read/write access only to necessary directories, limiting the damage if traversal succeeds.
Log and monitor file access:
Track unusual file access patterns (e.g., requests for system files) to detect exploitation attempts.

06Signs You May Already Be Affected

Check your application logs for requests containing unusual path sequences like ....//, ..../, or repeated dots. Look for file access attempts targeting files outside your intended upload or content directories (e.g., requests for /etc/passwd, configuration files, or source code). If you find evidence of successful access to files outside the intended scope, investigate whether sensitive data was exposed.

07Related Recent Vulnerabilities