cybersecurity · intermediate · ~20 min
Defensive string scanning for a well-defined set of malicious sub-patterns.
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:
.. segment delimited by / or \\ or string boundaries (e.g. .., a/.., ../b, a/../b, a\\..\\b).%2e%2e, %2E%2E, %2e%2E, %2E%2e (URL-encoded ..)./ are NOT traversal by themselves — only .. segments are.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
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.
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.
Null-terminated path candidate.
1 if any traversal pattern matches; otherwise 0.
O(strlen(path)). No allocations.
int has_path_traversal(const char *path) { /* TODO */ return 0; }
Using a single strstr for ".." — that catches "foo..bar" too. The dots must form a complete segment.
Empty input; literal ".." alone; double-dot inside a word ('foo..bar'); URL-encoded form.
O(n).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.