Safeguard
Application Security•

What is safe path handling and how do you stop path traversal?

Safe path handling means users reach only files you meant to expose. Resolve the full path, confirm it stays inside one folder, and avoid raw user input.

Safeguard Security Team
4 min read

Safe path handling means code that builds file paths from user input can only reach the files you intended. The reliable method is to resolve the final absolute path, check it still sits inside an allowed base folder, and avoid using raw user input in file names at all. Filtering the string "../" is not enough.

What goes wrong without it?

OWASP describes path traversal as manipulating file references with dot-dot-slash sequences, or absolute paths, to read files outside the web root. That can expose source code, configuration and system files. MITRE tracks the weakness as CWE-22, improper limitation of a pathname to a restricted directory.

A typical bug is a download endpoint that takes a file name and joins it to a folder. If the name is "report.pdf" it works. If the name climbs out of the folder, the server returns something else.

Why does string filtering fail?

Because there are too many spellings. Encoded slashes, doubled sequences, backslashes on Windows, and absolute paths all mean the same thing to the operating system. A blocklist that removes "../" once can be beaten by input that rebuilds it after removal. The check has to happen on the path the operating system will actually use, after all decoding and joining.

Symbolic links add another gap. A path can look like it is inside your folder while the link points elsewhere. Resolving links before the check closes that.

What is the safer pattern?

Three layers, from strongest to weakest:

  1. Do not let users choose paths. Store an ID in a database, map it to a file name you generated, and look it up.
  2. If you must accept a name, allow only a narrow set of characters and reject the rest.
  3. Resolve and compare. Join the base folder and the input, resolve it to an absolute canonical path, and confirm it begins with the base folder plus a separator.

The separator matters. A check that the path starts with "/srv/files" also accepts "/srv/files-private". Compare against "/srv/files/".

A constructed example

An app serves invoices from a folder called invoices. The handler joins the folder and the request parameter. A tester sends a parameter that climbs two levels and asks for the application's environment file. With the resolve-and-compare check, the resolved path is outside the base folder and the request gets a plain 404. With the ID lookup pattern, the question never arises, because the parameter is a number.

How does it differ by language?

The idea is the same everywhere. Node.js offers path.resolve and fs.realpath. Python has os.path.realpath and pathlib. Java has Path.normalize and toRealPath. Use your language's canonicalization call, then compare. Read the framework documentation too, because some static file helpers already do this and some do not.

What about writes and archives?

Path traversal is not only about reading. An upload handler, a log writer or an archive extractor that builds a destination from user-controlled names can overwrite files outside the intended folder. Archives are a classic case, because each entry carries its own path. Treat every entry name as untrusted input, resolve its destination, and refuse any that falls outside the extraction folder. Also decide what to do about links inside an archive, and when in doubt, skip them.

How to check or apply this

  1. Search the codebase for file reads and writes that use request data, including archive extraction, which can write outside a folder through crafted entry names.
  2. Replace direct user-supplied names with generated IDs where possible.
  3. For the rest, resolve the final path and confirm it stays under the base folder with a trailing separator.
  4. Run the application as a user that can only read the folders it needs.
  5. Add a test that requests a path outside the base folder and expects a failure.
  6. Run static analysis in CI so new instances are flagged in review.

Safeguard can run static analysis on your code from the IDE and in CI, which makes step 6 routine.

Quick check

Is removing "../" from input enough?

No. Encodings, absolute paths and repeated sequences get around simple removal. Resolve the final path and compare it to the allowed base folder.

Does a sandboxed container make this safe?

It limits the damage but does not fix the bug. The attacker can still read everything the application can read, including its secrets.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.