Lesson 1 of 3 in Path Traversal · 4 min left in this chapter
A Name That Climbs
Path traversal is what happens when a filename you supply is joined to a directory without confinement. `..` means "up one", and a path made of your input can climb out of the folder it was supposed to live in.
2 min read
Not yet reviewed
The app only lets me pick a log file. It is not asking me for a path — just a name. How much trouble can a name be?
A name is a path with one segment. And the code does not read *your name* — it reads your name joined to a folder. The join is where it goes wrong, because you get a say in the result.
A path is just segments
A file path is a list of segments separated by slashes, read left to right. Two of those segments are special: . means "this directory", and .. means "the parent". They are not filenames — they are *movements*. A path with .. in it does not name a place; it gives directions.
Path traversal is what happens when an application builds a path by gluing your input onto a directory, and then follows the directions you put in it. The application meant to say "the log folder, then whatever file they named". You say ../../../../etc/passwd, and the directions walk straight out of the log folder and across the disk.
How the path is built
const full = join('/var/log/app', req.query.file)
return read(full)What an attacker sends
file = "../../../../etc/passwd"join faithfully resolves the .. segments — that is its job — so the result is /etc/passwd, nowhere near the log folder. Nothing malfunctioned: the path said "up, up, up, up, then etc, then passwd", and it was followed.
Why does the application read the file at all, instead of refusing a filename that is obviously not a log?
../../../../etc/passwd is just a value to join and open, and open does not care which folder the app intended. The confinement the developer imagined was never written down anywhere the computer could enforce it.