Skip to content

Commit 86049e7

Browse files
Defend against multi-encoded unsafe API path segments
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 8088254 commit 86049e7

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

hyperbrowser/client/base.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,12 @@ def _build_url(self, path: str) -> str:
9090
normalized_query_suffix = (
9191
f"?{normalized_parts.query}" if normalized_parts.query else ""
9292
)
93-
decoded_path = unquote(normalized_path_only)
93+
decoded_path = normalized_path_only
94+
for _ in range(3):
95+
next_decoded_path = unquote(decoded_path)
96+
if next_decoded_path == decoded_path:
97+
break
98+
decoded_path = next_decoded_path
9499
if "\\" in decoded_path:
95100
raise HyperbrowserError("path must not contain backslashes")
96101
if "\n" in decoded_path or "\r" in decoded_path:

tests/test_url_building.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,26 @@ def test_client_build_url_rejects_empty_or_non_string_paths():
162162
HyperbrowserError, match="path must not contain relative path segments"
163163
):
164164
client._build_url("/api/%2E/session")
165+
with pytest.raises(
166+
HyperbrowserError, match="path must not contain relative path segments"
167+
):
168+
client._build_url("/%252e%252e/session")
165169
with pytest.raises(
166170
HyperbrowserError, match="path must not contain backslashes"
167171
):
168172
client._build_url("/api/%5Csession")
173+
with pytest.raises(
174+
HyperbrowserError, match="path must not contain backslashes"
175+
):
176+
client._build_url("/api/%255Csession")
169177
with pytest.raises(
170178
HyperbrowserError, match="path must not contain newline characters"
171179
):
172180
client._build_url("/api/%0Asegment")
181+
with pytest.raises(
182+
HyperbrowserError, match="path must not contain newline characters"
183+
):
184+
client._build_url("/api/%250Asegment")
173185
finally:
174186
client.close()
175187

0 commit comments

Comments
 (0)