Security

Path Traversal Vulnerability Examples — Python, Node.js

Path traversal (directory traversal) vulnerabilities let attackers read files outside the intended directory using ../ sequences. This guide shows real examples in Python and Node.js — the vulnerable pattern, how attackers exploit it, and the correct fix.


What is path traversal?

A path traversal vulnerability exists when an application uses user-controlled input to build a file path without validating that the resulting path stays within the intended directory. An attacker sends a filename like ../../etc/passwd to escape the uploads folder and read any file the server process can access.

Impact: Attackers can read application source code, configuration files, private keys, database credentials, and system files. OWASP ranks it A01 (Broken Access Control).


1

Python Flask — Path Traversal

Web frameworks that serve user-requested files are the most common vector.

❌ Attacker can read any file

@app.route('/download')
def download():
    filename = request.args.get('file')
    file_path = f"/var/app/uploads/{filename}"
    return send_file(file_path)
# Attack: GET /download?file=../../etc/passwd
# Returns: root:x:0:0:root:/root:/bin/bash ...

✅ Realpath + directory check

import os
from flask import abort

UPLOAD_DIR = os.path.realpath("/var/app/uploads")

@app.route('/download')
def download():
    filename = request.args.get('file', '')
    # Resolve ALL ../ and symlinks to absolute path
    safe_path = os.path.realpath(os.path.join(UPLOAD_DIR, filename))
    # Verify it's still inside the uploads directory
    if not safe_path.startswith(UPLOAD_DIR + os.sep):
        abort(403)  # Forbidden
    return send_file(safe_path)
2

Node.js Express — Path Traversal

Express file serving endpoints are vulnerable when using path.join with user input directly.

❌ Directory traversal in Express

app.get('/file', (req, res) => {
  const filename = req.query.name;
  const filePath = path.join(__dirname, 'uploads', filename);
  res.sendFile(filePath);
  // Attack: ?name=../../.env → exposes all env vars
  // path.join normalizes but does NOT prevent traversal

✅ path.resolve + startsWith check

const UPLOAD_DIR = path.resolve(__dirname, 'uploads');

app.get('/file', (req, res) => {
  const filename = req.query.name;
  const filePath = path.resolve(UPLOAD_DIR, filename);
  // Verify path stays within UPLOAD_DIR
  if (!filePath.startsWith(UPLOAD_DIR + path.sep)) {
    return res.status(403).send('Forbidden');
  }
  res.sendFile(filePath);
});
3

Python — File Upload Traversal

File uploads where the filename comes from the client are particularly dangerous.

❌ Using client filename directly

@app.route('/upload', methods=['POST'])
def upload():
    file = request.files['document']
    # Attacker sends filename: "../../app/config.py"
    file.save(os.path.join('/uploads', file.filename))
    # Overwrites application source code!

✅ werkzeug.utils.secure_filename

from werkzeug.utils import secure_filename
import uuid

@app.route('/upload', methods=['POST'])
def upload():
    file = request.files['document']
    # secure_filename strips all path components and dangerous chars
    safe_name = secure_filename(file.filename)
    if not safe_name:  # Empty after sanitization
        return "Invalid filename", 400
    # Use UUID to prevent filename conflicts and enumeration
    unique_name = f"{uuid.uuid4()}_{safe_name}"
    file.save(os.path.join('/uploads', unique_name))
💡

Pro tip: The safe pattern is always the same: os.path.realpath() (Python) or path.resolve() (Node.js) resolves all ../ sequences, then check that the result starts with your intended directory. Never trust client-provided filenames.


Detect Path Traversal in Your Code

Paste your code — LearnCodeGuide detects all these issues automatically using GPT-4o + Claude Sonnet. Free to start.

Analyze Your Code →

Related Guides

Path Traversal in PythonCommand Injection in PythonPython Security MistakesSQL Injection ExamplesSecurity Code Analysis

Published by LearnCodeGuide Team · Last reviewed: November 2025