cybersecurity · intermediate · ~20 min

Detect path-traversal patterns in a string

Defensive string scanning for a well-defined set of malicious sub-patterns.

Challenge

Implement int has_path_traversal(const char *path) returning 1 if path contains any obvious path-traversal pattern, else 0.

Treat the following as traversal:

  • Any .. segment delimited by / or \\ or string boundaries (e.g. .., a/.., ../b, a/../b, a\\..\\b).
  • The literal substrings %2e%2e, %2E%2E, %2e%2E, %2E%2e (URL-encoded ..).
  • Plain absolute paths starting with / are NOT traversal by themselves — only .. segments are.

Examples

has_path_traversal("foo/bar")          -> 0
has_path_traversal("..")               -> 1
has_path_traversal("../etc/passwd")    -> 1
has_path_traversal("foo/../bar")       -> 1
has_path_traversal("foo..bar")         -> 0   // ".." inside a name, not a segment
has_path_traversal("..\\Windows")    -> 1
has_path_traversal("%2e%2e/foo")       -> 1
has_path_traversal("/etc/passwd")      -> 0
has_path_traversal("")                 -> 0

Why this matters (safety note)

This is a defensive check used to reject untrusted input before opening files. It is NOT an attack tool. Production code should also canonicalise the path with realpath and verify the result starts with the allowed root directory — string checks alone are not sufficient.

Why this matters

Web servers and file-API gateways must reject paths like ../../../etc/passwd before opening anything. The check looks simple but has subtle traps — URL-encoded %2e%2e, mid-string .., and Windows ..\ are all real-world bypasses.

Input format

Null-terminated path candidate.

Output format

1 if any traversal pattern matches; otherwise 0.

Constraints

O(strlen(path)). No allocations.

Starter code

int has_path_traversal(const char *path) { /* TODO */ return 0; }

Common mistakes

Using a single strstr for ".." — that catches "foo..bar" too. The dots must form a complete segment.

Edge cases to handle

Empty input; literal ".." alone; double-dot inside a word ('foo..bar'); URL-encoded form.

Complexity

O(n).

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.