Skip to content

Commit ad3e469

Browse files
Harden URL builder against runtime base_url misconfiguration
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent d883807 commit ad3e469

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

hyperbrowser/client/base.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,19 @@ def _build_url(self, path: str) -> str:
8787
normalized_query_suffix = (
8888
f"?{normalized_parts.query}" if normalized_parts.query else ""
8989
)
90-
base_has_api_suffix = (
91-
urlparse(self.config.base_url).path.rstrip("/").endswith("/api")
92-
)
90+
parsed_base_url = urlparse(self.config.base_url)
91+
if (
92+
parsed_base_url.scheme not in {"https", "http"}
93+
or not parsed_base_url.netloc
94+
):
95+
raise HyperbrowserError(
96+
"base_url must start with 'https://' or 'http://' and include a host"
97+
)
98+
if parsed_base_url.query or parsed_base_url.fragment:
99+
raise HyperbrowserError(
100+
"base_url must not include query parameters or fragments"
101+
)
102+
base_has_api_suffix = parsed_base_url.path.rstrip("/").endswith("/api")
93103

94104
if normalized_path_only == "/api" or normalized_path_only.startswith("/api/"):
95105
if base_has_api_suffix:

tests/test_url_building.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,22 @@ def test_client_build_url_reflects_runtime_base_url_changes():
8585
client.close()
8686

8787

88+
def test_client_build_url_rejects_runtime_invalid_base_url_changes():
89+
client = Hyperbrowser(config=ClientConfig(api_key="test-key"))
90+
try:
91+
client.config.base_url = "invalid-base-url"
92+
with pytest.raises(HyperbrowserError, match="include a host"):
93+
client._build_url("/session")
94+
95+
client.config.base_url = "https://example.local?foo=bar"
96+
with pytest.raises(
97+
HyperbrowserError, match="must not include query parameters"
98+
):
99+
client._build_url("/session")
100+
finally:
101+
client.close()
102+
103+
88104
def test_client_build_url_rejects_empty_or_non_string_paths():
89105
client = Hyperbrowser(config=ClientConfig(api_key="test-key"))
90106
try:

0 commit comments

Comments
 (0)