Skip to content
>_ITDITDWeb Security Platform

Glossary

What is path traversal — reading files the server should never serve, via ../

Path traversal (directory traversal) mixes ../ into a filename input to read or write files outside the intended folder — .env, config, keys, /etc. How it works, and the real defense (don't use input as a path; confine to a base directory) — explained defensively, no attack steps.

Published 2026-06-10 Updated 2026-06-10 3 min read

"Put ../ in the filename field and the server's deep .env becomes readable" — that's path traversal. Here's how it works and how to reliably prevent it (no attack steps).

Where it shows up

Anywhere "user input picks a file."

FeatureThe risky use
Download / previewUsing ?file= as the filename directly
Image / attachment displayBuilding part of the path from a URL parameter
UploadUsing a user-supplied name in the save path (write type — most dangerous)
Template / locale loadingPicking a file dynamically via ?lang= etc.

Why it works

../ means "up one level." If the app concatenates public folder + user input and opens that file, stacked ../ segments let the request "walk" out of the public folder.

Intended: /var/www/files/ + user input
Input stacks "up a level" (../ ../ ../ …)
↓ app concatenates without normalizing, then open()
Reaches outside the base (.env, config, keys, /etc) = read/write
Concatenate user input onto the base folder and stacked ../ reaches files outside it.

Reading means disclosure; writing (uploads) means files planted anywhere, which can lead to RCE.

Defense: don't use input as a path + confine to the base

1

Never use user input as a raw file path (most important)

Resolve exposed files through an ID → real-file allowlist. The user passes only an identifier ("3", "invoice"); the server decides the real path.

2

Normalize, then verify it stays inside the base directory

Turn it into an absolute path with the language's resolver (resolve/realpath), then check it starts with the allowed base directory. Reject anything outside. Naive '../' string-stripping fails to encoding bypasses.

3

Run the app with least privilege

Limit which files the app's runtime user can read to what the job needs. Even if someone escapes, unreadable files leak nothing.

4

Keep secrets out of the public root entirely

Don't place .env, .git, keys, or backups in the web root or upload folder in the first place. Remove the attack surface by placement.

This site's view: it's continuous with placement mistakes — fix in the right order

Path traversal is continuous with the .env exposure incident: both are "something that should never be reachable over the web becomes reachable over the web." First aid (headers, naive filters) hides the symptom; if the code and placement aren't fixed, another route still leaks. The order is (1) code that doesn't use input as a path, (2) base-directory confinement, (3) keep secrets out of the public root. Read safe placement on shared hosting alongside this for the real-fix shape.

FAQ

QWhat leaks in path traversal?
A

Files the app was never meant to expose: .env (DB creds, API keys), config files, private keys, source code, OS paths like /etc. Beyond reading, if it reaches an upload's destination path it can write anywhere and escalate to RCE (remote code execution).

QWhat's the top defense?
A

Never use user input as a raw file path. If you must, map it through an allowlist (a fixed set of IDs/filenames), normalize the path with a library, and verify the result stays inside the allowed base directory. Extension checks or naive '../' stripping get bypassed.

QCan I just block it with .htaccess or headers?
A

That's first aid for a different problem (sensitive files sitting in the web root). The root fix is placing the app body, .env, and .git OUTSIDE the public root, plus code that doesn't use input as a path. First aid and the real fix are separate jobs.