01Summary

Path traversal is a vulnerability that allows an attacker to access files or directories outside the intended restricted location by manipulating file paths with special sequences like .. (parent directory). When user input is used to construct file paths without proper validation, an attacker can escape the intended directory boundary and read, write, or delete sensitive files anywhere the application has permission to access.

02How It Happens

Applications often need to serve files or access data based on user input — for example, allowing a user to download a document by filename, or retrieve a user-uploaded image. If the application directly concatenates user-supplied input into a file path without sanitizing special directory traversal characters, an attacker can inject .. sequences to navigate up the directory tree. The application may intend to restrict access to /var/www/uploads/, but if it naively joins user input like ../../etc/passwd to that base path, the resulting path resolves outside the intended boundary. The operating system then follows the path as written, granting access to files the application should never expose.

03Real-World Impact

Successful path traversal can expose sensitive configuration files, private keys, database credentials, or source code. In write scenarios, an attacker might overwrite application files or inject malicious code. On shared hosting or multi-tenant systems, an attacker could access other users' data. The severity depends on what files the application process can reach — a web server running as root is far more dangerous than one in a sandboxed container, but both are vulnerable if the path traversal exists.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import os

def serve_file(filename):
    base_dir = "/var/www/uploads"
    file_path = os.path.join(base_dir, filename)
    with open(file_path, 'r') as f:
        return f.read()

# User requests: "../../etc/passwd"
# Resulting path: /etc/passwd (outside base_dir)

Why it's vulnerable:
The code joins user input directly to the base directory without checking whether the resolved path stays within bounds. The .. sequences are processed by the OS, allowing escape from the intended directory.

Fixed pattern
import os

def serve_file(filename):
    base_dir = "/var/www/uploads"
    file_path = os.path.abspath(os.path.join(base_dir, filename))
    
    # Verify the resolved path is still under base_dir
    if not file_path.startswith(os.path.abspath(base_dir) + os.sep):
        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";
$filename = $_GET['file'];
$file_path = $base_dir . "/" . $filename;

// User requests: "../../etc/passwd"
// Resulting path: /etc/passwd (outside base_dir)
readfile($file_path);
?>

Why it's vulnerable:
User input is concatenated directly into the file path. No validation prevents .. or absolute paths from escaping the intended directory.

Fixed pattern
<?php
$base_dir = "/var/www/uploads";
$filename = $_GET['file'];

// Remove any path traversal sequences
$filename = basename($filename);

// Alternatively, use realpath and verify containment
$file_path = realpath($base_dir . "/" . $filename);
$base_real = realpath($base_dir);

if ($file_path === false || strpos($file_path, $base_real) !== 0) {
    die("Access denied: invalid file path");
}

readfile($file_path);
?>

05Prevention Checklist

Use allowlisting, not blacklisting.
Instead of trying to block .., ./, and other sequences, explicitly allow only safe characters (alphanumeric, underscore, hyphen, dot) in filenames.
Resolve and verify paths.
Use realpath() (PHP) or os.path.abspath() (Python) to resolve the final path, then confirm it starts with the intended base directory.
Use basename() for filenames.
If you only need the filename component (not subdirectories), basename() strips any directory traversal attempts.
Avoid user input in file paths when possible.
Use a database or mapping table to associate user-friendly identifiers with safe internal filenames.
Run with minimal privileges.
Ensure the application process has permission only to access files it legitimately needs; this limits damage if traversal succeeds.
Log and monitor file access.
Unexpected attempts to access files outside the intended directory may indicate an attack in progress.

06Signs You May Already Be Affected

Check your application logs for requests containing .., ./, or encoded variants (%2e%2e, ..%2f). Review file access logs for unexpected reads of sensitive files like configuration files, private keys, or system files. If you find evidence of such requests, investigate whether they succeeded and what data may have been exposed.

07Related Recent Vulnerabilities

CVE-2026-105772 Arbitrary file read and write in Google ADK TypeScript (@google/adk) FileArtifactService via path traversal in userId and sessionId CVSS 9.1/10 CRITICAL CVE-2026-111925 Mopidy before 4.0.5 Path Traversal via File Backend library.lookup CVSS 6.9/10 MEDIUM CVE-2026-111915 Yank Note before 3.93.1 Path Traversal via /api/help Endpoint CVSS 8.2/10 HIGH CVE-2026-79986 Apache Camel: camel-azure-files resolved the remote path of a polled file from the name reported in the server directory listing without constraining it to the directory being polled, so a listing entry containing traversal segments could be moved outside CVSS 7.4/10 HIGH CVE-2026-79985 Apache Camel: camel-smb resolved the remote path of a polled file from the name reported in the server directory listing without constraining it to the directory being polled, so a listing entry containing traversal segments could be moved outside CVSS 7.4/10 HIGH CVE-2026-79984 Apache Camel: camel-mina-sftp resolved the remote path of a polled file from the name reported in the server directory listing without constraining it to the directory being polled, so a listing entry containing traversal segments could be moved outside CVSS 7.4/10 HIGH CVE-2026-79983 Apache Camel: camel-ftp resolved the remote path of a polled file from the name reported in the server directory listing without constraining it to the directory being polled, so a listing entry containing traversal segments could be moved outside CVSS 7.4/10 HIGH CVE-2026-110253 weForms <= 1.6.28 - Unauthenticated Limited Media File Deletion via 'wpuf_files' Parameter CVSS 5.4/10 MEDIUM CVE-2026-93767 Tainacan <= 1.3.0 - Authenticated (Subscriber+) Path Traversal to Arbitrary File Read via 'guid' Parameter CVSS 6.5/10 MEDIUM CVE-2026-84823 Org.wildfly.core: wildfly: path traversal in take-snapshot discloses the server configuration to the monitor role CVSS 7.1/10 HIGH