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.
"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."
| Feature | The risky use |
|---|---|
| Download / preview | Using ?file= as the filename directly |
| Image / attachment display | Building part of the path from a URL parameter |
| Upload | Using a user-supplied name in the save path (write type — most dangerous) |
| Template / locale loading | Picking 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.
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
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.
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.
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.
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.
Read next
- Incident: Exposing the entire .env file
- Defense: Protecting .env on shared hosting · Glossary: What is RCE
FAQ
QWhat leaks in path traversal?
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?
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?
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.