Path traversal is when putting ../ in a filename field makes a .env file deep on the server readable. 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 reach files outside 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. Placement alone removes what could be attacked.
This site's view: it's the same kind of problem as placement mistakes, so fix things in the right order
Path traversal is the same kind of problem as the .env exposure incident: both are "something that should never be reachable over the web becomes reachable over the web." Temporary measures (headers, naive filters) only cover the surface; 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 to see how the root fix works.
How it differs from similar problems
The result can look the same, "a file that should be private is readable from outside," but the cause decides where you fix it.
| Problem | Cause | Where to fix |
|---|---|---|
| Path traversal | An input that points to a file can escape the allowed location | App code (don't use input as a path) |
| Local file inclusion (LFI) | The input chooses a file the program loads and runs | App code (fix which files can be loaded) |
| Files left in a public directory | .env or .git sits where the web can see it (→ secrets left in public directories) | File placement and web server settings |
| IDOR | The file ID has a valid format but can point to someone else's file | App permission checks |
Real examples: flaws in the web server itself
Path traversal is found not only in custom apps but also in widely used products.
- Apache HTTP Server 2.4.49 (2021): It had a path traversal flaw (CVE-2021-41773), and the Apache project stated it was known to be exploited in the wild. Version 2.4.50 fixed it, but the fix was incomplete (CVE-2021-42013), so it was fixed again in 2.4.51. Depending on configuration, it led not only to file reads but also to RCE.
- WordPress core (2026): Path traversal in the code that resolves page templates led to a file inclusion flaw (CVE-2026-87902) that can reach RCE under certain conditions (→ CVE-2026-87902 explained).
In May 2024, the US agencies CISA and FBI issued an alert asking manufacturers to eliminate this class of flaw. At that point, they said, CISA's KEV (the list of vulnerabilities confirmed as exploited) contained 55 directory traversal vulnerabilities. In MITRE's "CWE Top 25" published in December 2025, path traversal (CWE-22) ranks sixth.
How to check your own site
Find file operations that take input
Search your code for functions that open or send files (open, readFile, sendFile, include and so on) or build paths (path.join and similar) where request values can end up.
Check the order of the checks
Where input is used, confirm that the path is normalized first (path.resolve or realpath) and only then checked to be inside the base directory. If the code only inspects the string before normalizing, fix the order.
Check your web server and product versions
Make sure you are not running versions with known path traversal, such as Apache 2.4.49 or 2.4.50. The CVE / KEV Lookup shows known vulnerabilities in the products you use.
Check for files that must not be visible
Use the site audit to check that .env, .git and database dumps cannot be read from outside. If they can, fix the placement as a separate job from path traversal.
Sources (primary)
- CISA and FBI, "Secure by Design Alert: Eliminating Directory Traversal Vulnerabilities in Software" (May 2, 2024) — cisa.gov (55 entries in KEV, using random identifiers)
- Apache HTTP Server, "Apache HTTP Server 2.4 vulnerabilities" — httpd.apache.org (CVE-2021-41773, CVE-2021-42013)
- MITRE, "2025 CWE Top 25 Most Dangerous Software Weaknesses" (December 2025) — cwe.mitre.org (CWE-22 ranked sixth)
- OWASP, "Path Traversal" — owasp.org
- IPA, "How to Secure Your Web Site" — ipa.go.jp (Japanese; unchecked path parameters / directory traversal)
Read next
- Incident: Exposing the entire .env file
- Defense: Protecting .env on shared hosting · Glossary: What is RCE