fix(tools): tighten web fetch URL cleaning

Made-with: Cursor
This commit is contained in:
Xubin Ren
2026-05-01 19:58:19 +08:00
committed by Xubin Ren
parent 5dc96505e8
commit aea5948b11
2 changed files with 22 additions and 6 deletions
+1 -3
View File
@@ -388,9 +388,7 @@ class WebFetchTool(Tool):
max_chars: int | None = None,
**kwargs: Any,
) -> Any:
url = url.strip().strip("`").strip('"').strip("'")
if not (url.startswith("http://") or url.startswith("https://")):
return json.dumps({"error": "Invalid URL after cleaning", "url": url}, ensure_ascii=False)
url = url.strip(" \t\r\n`\"'")
extract_mode = kwargs.pop("extractMode", extract_mode)
max_chars = kwargs.pop("maxChars", max_chars) or self.max_chars
is_valid, error_msg = _validate_url_safe(url)
+21 -3
View File
@@ -110,6 +110,24 @@ async def test_execute_strips_space_and_backticks():
assert "error" not in data, f"unexpected error: {data}"
@pytest.mark.asyncio
async def test_execute_strips_mixed_markdown_and_quotes():
tool = WebFetchTool()
with _patch_env()[0], _patch_env()[1]:
result = await tool.execute(url='"`https://example.com/page`"')
data = json.loads(result)
assert "error" not in data, f"unexpected error: {data}"
@pytest.mark.asyncio
async def test_execute_keeps_case_insensitive_http_scheme():
tool = WebFetchTool()
with _patch_env()[0], _patch_env()[1]:
result = await tool.execute(url="HTTPS://example.com/page")
data = json.loads(result)
assert "error" not in data, f"unexpected error: {data}"
# --- startswith guard tests ---
@pytest.mark.asyncio
@@ -118,7 +136,7 @@ async def test_execute_rejects_non_http_url_after_cleaning():
result = await tool.execute(url="ftp://example.com/file")
data = json.loads(result)
assert "error" in data
assert "Invalid URL" in data["error"]
assert "URL validation failed" in data["error"]
@pytest.mark.asyncio
@@ -127,7 +145,7 @@ async def test_execute_rejects_garbage_after_cleaning():
result = await tool.execute(url="`not a url at all`")
data = json.loads(result)
assert "error" in data
assert "Invalid URL" in data["error"]
assert "URL validation failed" in data["error"]
@pytest.mark.asyncio
@@ -136,4 +154,4 @@ async def test_execute_rejects_bare_domain_after_cleaning():
result = await tool.execute(url="`example.com/page`")
data = json.loads(result)
assert "error" in data
assert "Invalid URL" in data["error"]
assert "URL validation failed" in data["error"]