From 6af99423272ed67dd1f8d88bfdf762d4e5b77a2f Mon Sep 17 00:00:00 2001 From: aydnOktay Date: Tue, 24 Mar 2026 13:45:33 +0300 Subject: [PATCH] fix(url-safety): allow only http and https schemes --- tests/tools/test_url_safety.py | 8 ++++++++ tools/url_safety.py | 3 +++ 2 files changed, 11 insertions(+) diff --git a/tests/tools/test_url_safety.py b/tests/tools/test_url_safety.py index 38d27d40af3..5a0cceb2880 100644 --- a/tests/tools/test_url_safety.py +++ b/tests/tools/test_url_safety.py @@ -22,6 +22,14 @@ class TestIsSafeUrl: ]): assert is_safe_url("https://example.com/image.png") is True + def test_ftp_scheme_blocked(self): + """Only http/https should be allowed for fetch tools.""" + assert is_safe_url("ftp://example.com/file.txt") is False + + def test_missing_scheme_blocked(self): + """Bare host/path should be rejected to avoid ambiguous handling.""" + assert is_safe_url("example.com/path") is False + def test_localhost_blocked(self): with patch("socket.getaddrinfo", return_value=[ (2, 1, 6, "", ("127.0.0.1", 0)), diff --git a/tools/url_safety.py b/tools/url_safety.py index 743510b2757..0f3dd597e49 100644 --- a/tools/url_safety.py +++ b/tools/url_safety.py @@ -263,6 +263,9 @@ def is_safe_url(url: str) -> bool: parsed = urlparse(url) hostname = (parsed.hostname or "").strip().lower().rstrip(".") scheme = (parsed.scheme or "").strip().lower() + if scheme not in {"http", "https"}: + logger.warning("Blocked request — unsupported URL scheme: %s", scheme or "") + return False if not hostname: return False