Path traversal is what happens when a server takes a filename from the user and trusts it. GET /files?name=../../../../etc/passwd is the cliché, but the bug shows up everywhere file paths meet user input: download endpoints, image proxies, archive extractors (the so-called "zip slip"), template loaders, plugin systems.

The defense is to construct the absolute path and then verify it lives under the directory you intended. Languages and stdlibs differ in the right helper — path.join followed by a path.relative containment check, or Python's pathlib.PurePath.is_relative_to, or Go's filepath.Clean plus a strict prefix test. Always perform the check after path normalization, because ../, ..\, percent-encoded variants, and Unicode look-alikes all need to be folded to their canonical form before comparison.

Allowlist over blocklist. Strip .. is not a safe primitive: attackers will find encodings you didn't think of. Compute the resolved path and verify it's inside the safe root by exact prefix.

Review heuristic

Whenever filesystem path concatenation meets a request value, verify there's a containment check on the resolved absolute path. The check has to come after normalization and has to fail closed (reject by default), not by string-stripping ...

External reference

CWE-22: Path Traversal — the canonical industry classification for this bug class. Useful when filing tickets, writing security policies, or arguing with a static analyzer.