deer-flow/backend/tests/test_ddg_image_search_urls.py
huyengiang101086-spec 6783073a39
fix(image-search): share public result URL screening (#6740)
* fix(image-search): screen DuckDuckGo result URLs

* fix(image-search): unify provider result URL screening

* docs(image-search): scope URL guidance to avoid inherited size limits

---------

Co-authored-by: huyengiang101086-spec <270684046+huyengiang101086-spec@users.noreply.github.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-10-13 15:50:45 +08:00

53 lines
2.4 KiB
Python

import json
from unittest.mock import patch
import pytest
from deerflow.community.image_search import tools
from deerflow.community.url_safety import safe_public_result_url
@pytest.mark.asyncio
async def test_image_search_drops_unsafe_result_urls() -> None:
rows = [
{"title": "safe", "image": "https://images.example/full.jpg", "thumbnail": "https://images.example/thumb.jpg"},
{"title": "unsafe original", "image": "http://127.0.0.1/private", "thumbnail": "https://images.example/thumb2.jpg"},
{"title": "unsafe thumbnail", "image": "https://images.example/full3.jpg", "thumbnail": "javascript:alert(1)"},
{"title": "both unsafe", "image": "http://2130706433/private", "thumbnail": "http://localhost/thumb"},
]
with patch.object(tools, "_search_images", return_value=rows), patch.object(tools, "get_app_config") as config:
config.return_value.get_tool_config.return_value = None
result = json.loads(await tools.image_search_tool.ainvoke({"query": "reference"}))
assert result["total_results"] == 3
assert result["results"] == [
{"title": "safe", "image_url": "https://images.example/full.jpg", "thumbnail_url": "https://images.example/thumb.jpg"},
{"title": "unsafe original", "image_url": "", "thumbnail_url": "https://images.example/thumb2.jpg"},
{"title": "unsafe thumbnail", "image_url": "https://images.example/full3.jpg", "thumbnail_url": ""},
]
@pytest.mark.asyncio
async def test_image_search_reports_when_all_urls_are_unsafe() -> None:
with patch.object(tools, "_search_images", return_value=[{"title": "local", "image": "http://[::1]/image"}]), patch.object(tools, "get_app_config") as config:
config.return_value.get_tool_config.return_value = None
result = json.loads(await tools.image_search_tool.ainvoke({"query": "reference"}))
assert result == {"error": "No safe image URLs found", "query": "reference"}
@pytest.mark.parametrize(
"url",
[
"file:///etc/passwd",
"http://metadata.google.internal/computeMetadata/v1/",
"http://127.0.0.1/image",
"http://0177.0.0.1/image",
"http://0x7f000001/image",
"http://[::ffff:127.0.0.1]/image",
"http://[64:ff9b::7f00:1]/image",
],
)
def test_image_search_rejects_local_result_url_spellings(url: str) -> None:
assert safe_public_result_url(url) == ""