Merge pull request #3705 from rudycelekli/fix/cow50-search-anonymous-opt-in-20261012

fix(search): require explicit anonymous provider opt-in
This commit is contained in:
zhayujie authored and GitHub committed 2026-10-16 16:42:09 +08:00
commit a54eea60fb
3 files changed
+49 -4

No files matched your search

+15 -2
View File
@@ -114,14 +114,27 @@ def _get_api_key(provider: str) -> str:
return ""
def anonymous_opt_in(value) -> bool:
"""Whether a config value explicitly enables keyless search. Anything not
clearly "on" (e.g. the string "false") stays off, since it sends queries
to a third party."""
if isinstance(value, bool):
return value
if isinstance(value, int):
return value == 1
if isinstance(value, str):
return value.strip().lower() in ("true", "1", "yes", "on")
return False
def _anysearch_anonymous_enabled() -> bool:
"""Check if AnySearch anonymous mode is enabled via config."""
return bool(_tools_web_search_conf().get("anysearch_anonymous"))
return anonymous_opt_in(_tools_web_search_conf().get("anysearch_anonymous"))
def _keenable_anonymous_enabled() -> bool:
"""Check if Keenable anonymous (keyless) mode is enabled via config."""
return bool(_tools_web_search_conf().get("keenable_anonymous"))
return anonymous_opt_in(_tools_web_search_conf().get("keenable_anonymous"))
def _get_searxng_url() -> str:
+4 -2
View File
@@ -1489,8 +1489,10 @@ class ModelsHandler:
if not isinstance(ws_cfg, dict):
ws_cfg = {}
anonymous_on = bool(ws_cfg.get("anysearch_anonymous"))
keenable_anonymous_on = bool(ws_cfg.get("keenable_anonymous"))
from agent.tools.web_search.web_search import anonymous_opt_in
anonymous_on = anonymous_opt_in(ws_cfg.get("anysearch_anonymous"))
keenable_anonymous_on = anonymous_opt_in(ws_cfg.get("keenable_anonymous"))
searxng_url = (ws_cfg.get("searxng_url") or "").strip() if isinstance(ws_cfg, dict) else ""
providers = []
configured_ids = []
@@ -0,0 +1,30 @@
import pytest
from agent.tools.web_search import web_search as ws
@pytest.mark.parametrize('value', ['false', 'off', '0', '', None, 0, [], {'invalid': True}])
def test_anonymous_search_requires_boolean_opt_in(monkeypatch, value):
monkeypatch.setattr(ws, '_get_api_key', lambda provider: '')
monkeypatch.setattr(ws, '_get_searxng_url', lambda: '')
monkeypatch.setattr(ws, 'conf', lambda: {'tools': {'web_search': {'anysearch_anonymous': value, 'keenable_anonymous': value}}})
assert ws.configured_providers() == []
def test_explicit_opt_in_and_api_key_configuration_remain_supported(monkeypatch):
monkeypatch.setattr(ws, '_get_api_key', lambda provider: 'fake-key' if provider == 'tavily' else '')
monkeypatch.setattr(ws, '_get_searxng_url', lambda: '')
monkeypatch.setattr(ws, 'conf', lambda: {'tools': {'web_search': {'anysearch_anonymous': True, 'keenable_anonymous': True}}})
assert ws.configured_providers() == ['anysearch', 'tavily', 'keenable']
@pytest.mark.parametrize('value', [True, 'true', 'True', 'yes', 'on', '1', 1])
def test_explicit_on_values_enable_anonymous_search(value):
assert ws.anonymous_opt_in(value) is True
def test_console_status_matches_the_tool(monkeypatch):
from channel.web.api.models import ModelsHandler
cfg = {'tools': {'web_search': {'anysearch_anonymous': 'false', 'keenable_anonymous': 'false'}}}
providers = {p['id']: p for p in ModelsHandler._search_capability(cfg)['providers']}
assert not providers['anysearch'].get('configured')
assert not providers['keenable'].get('configured')