All vulnerabilities
HighA01:2021CWE-22Broken Access Control

Path Traversal

Path traversal lets attackers access files outside the intended directory by injecting ../ sequences into file path parameters, exposing server configuration, credentials, and source code.

What Is Path Traversal?

Path traversal (also called directory traversal or Local File Inclusion) occurs when user input is used to construct a file path without proper validation. By injecting ../ sequences, an attacker can navigate outside the intended directory and read arbitrary files on the server.

How It Works

An endpoint that serves user-uploaded files:

# Vulnerable — user controls the filename
@app.get("/files/{filename}")
async def get_file(filename: str):
    file_path = f"/app/uploads/{filename}"
    with open(file_path, "rb") as f:
        return f.read()

Attacker requests:

GET /files/../../etc/passwd
GET /files/../../app/.env
GET /files/../../proc/self/environ

The path resolves to /etc/passwd, leaking all system user accounts and potentially password hashes.

Real-World Impact

  • Credential theft — read .env files with database passwords and API keys
  • Source code exposure — read application source, revealing business logic and further vulnerabilities
  • System enumeration — read /etc/passwd, /etc/hosts, /proc/ data
  • Private key theft — read SSH keys, TLS certificates stored on the filesystem
  • Config file access — database connection strings, cloud credentials

How to Fix

Resolve and validate the path before reading:

import os
 
UPLOAD_DIR = "/app/uploads"
 
@app.get("/files/{filename}")
async def get_file(filename: str):
    # Resolve symlinks and normalize the path
    requested = os.path.realpath(os.path.join(UPLOAD_DIR, filename))
 
    # Ensure the resolved path is still within the allowed directory
    if not requested.startswith(os.path.realpath(UPLOAD_DIR) + os.sep):
        raise HTTPException(status_code=403, detail="Access denied")
 
    with open(requested, "rb") as f:
        return f.read()

Strip dangerous characters from filenames:

import re
 
def sanitize_filename(name: str) -> str:
    # Allow only alphanumerics, dashes, underscores, dots
    return re.sub(r"[^a-zA-Z0-9_\-.]", "", name)

Use indirect references — store files with random IDs, map them server-side:

# Store: {"abc123": "/app/uploads/user42/report.pdf"}
# Serve: GET /files/abc123  — user never controls the actual path

What VibeWShield Detects

VibeWShield tests file-serving endpoints with path traversal payloads including URL-encoded variants (%2e%2e%2f), double-encoded (%252e%252e%252f), and null byte injection. It looks for known file signatures (root:x:0:0, [general], PEM headers) in responses.

#path-traversal#file#directory#lfi

Free security scan

Test your app for Path Traversal

VibeWShield automatically checks for Path Traversal and 40+ other vulnerabilities using 63 scanners — in under 3 minutes, no signup required.

Scan your app free