Skip to content

Commit ad5eadb

Browse files
committed
create normalize_path: Also normalizes /./ into /
1 parent 87508ae commit ad5eadb

2 files changed

Lines changed: 45 additions & 6 deletions

File tree

aikido_zen/vulnerabilities/path_traversal/detect_path_traversal_test.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,29 @@ def test_does_not_absolute_path_inside_another_folder():
106106

107107
def test_disable_checkPathStart():
108108
assert detect_path_traversal("/etc/passwd", "/etc/passwd", False) is False
109+
110+
111+
def test_current_directory_references():
112+
"""/./ should be normalized to /"""
113+
assert detect_path_traversal("/./etc/passwd", "/./etc") is True
114+
assert detect_path_traversal("/etc/./passwd", "/etc") is True
115+
assert detect_path_traversal("/etc/./passwd", "/etc/./") is True
116+
assert detect_path_traversal("/./etc/passwd", "/./etc/passwd") is True
117+
assert detect_path_traversal("/etc/./passwd", "/etc/./passwd") is True
118+
assert detect_path_traversal("/./etc/./passwd", "/./etc/./passwd") is True
119+
# Multiple /./ sequences
120+
assert detect_path_traversal("/././etc/passwd", "/././etc") is True
121+
assert detect_path_traversal("/etc/././passwd", "/etc/././passwd") is True
122+
123+
124+
def test_path_normalization():
125+
"""Paths with multiple slashes and /./ should be normalized and detected"""
126+
assert detect_path_traversal("//etc//passwd", "/etc") is True
127+
assert detect_path_traversal("/./etc/./passwd", "/etc") is True
128+
assert detect_path_traversal("/././etc/passwd", "/etc") is True
129+
# Paths without leading slash are not unsafe
130+
assert detect_path_traversal("etc/passwd", "etc") is False
131+
assert detect_path_traversal("", "") is False
132+
# Combined slashes and dot: ///.///etc/passwd should normalize to /etc/passwd
133+
assert detect_path_traversal("///.///etc/passwd", "///.///etc") is True
134+
assert detect_path_traversal("///.///etc/passwd", "///.///etc/passwd") is True

aikido_zen/vulnerabilities/path_traversal/unsafe_path_start.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
"""Exports the function starts_with_unsafe_path"""
22

3+
import regex as re
4+
5+
CURRENT_DIR_PATTERN = re.compile(r"/(\./)+")
6+
37
linux_root_folders = [
48
"/bin/",
59
"/boot/",
@@ -31,8 +35,8 @@
3135

3236
def starts_with_unsafe_path(file_path, user_input):
3337
"""Check if the file path starts with any dangerous paths and the user input."""
34-
path_parsed = ensure_one_leading_slash(file_path.lower())
35-
input_parsed = ensure_one_leading_slash(user_input.lower())
38+
path_parsed = normalize_path(file_path)
39+
input_parsed = normalize_path(user_input)
3640

3741
for dangerous_start in dangerous_path_starts:
3842
if path_parsed.startswith(dangerous_start) and path_parsed.startswith(
@@ -43,7 +47,16 @@ def starts_with_unsafe_path(file_path, user_input):
4347
return False
4448

4549

46-
def ensure_one_leading_slash(path: str) -> str:
47-
if path.startswith("/"):
48-
return "/" + path.lstrip("/")
49-
return path
50+
def normalize_path(path: str) -> str:
51+
"""Normalizes a path by lowercasing, removing /./ and removing consecutive slashes"""
52+
if not path:
53+
return path
54+
55+
normalized = path.lower()
56+
57+
# Matches /./ or /././ or /./././ etc. (one or more ./ sequences after a /)
58+
normalized = CURRENT_DIR_PATTERN.sub("/", normalized)
59+
60+
# Merge consecutive slashes since these don't change where you are in the path.
61+
normalized = re.sub(r"/+", "/", normalized)
62+
return normalized

0 commit comments

Comments
 (0)