ForcePilot/backend/package/yuxi/agents/toolkits/buildin/crawl/security.py

52 lines
1.7 KiB
Python
Raw Normal View History

"""爬取专用安全防护SSRF 校验、User-Agent、robots.txt 开关。
不复用 url_fetcher._get_validator() 的环境变量路径直接使用 config.get_ssrf_policy()
避免双路径漂移
"""
from urllib.parse import urlparse
from yuxi.config import config
from yuxi.utils.net_security import SSRFValidator, log_ssrf_block
_crawl_validator: SSRFValidator | None = None
def get_crawl_validator() -> SSRFValidator:
"""构建爬取专用的 SSRFValidator使用 config.get_ssrf_policy()。
不复用 url_fetcher._get_validator() 的环境变量路径避免双路径漂移
每次调用构建新实例会导致 DNS Pinning 缓存失效故采用模块级单例
"""
global _crawl_validator
if _crawl_validator is None:
_crawl_validator = SSRFValidator(config.get_ssrf_policy())
return _crawl_validator
async def validate_crawl_url(url: str) -> tuple[bool, str]:
"""爬取前的 SSRF 校验入口。
返回 (是否通过, 原因描述)通过时 reason 为校验器返回的通过描述
命中黑名单时记录审计日志仅主机名不暴露内网信息
"""
validator = get_crawl_validator()
ok, reason = await validator.validate_url(url)
if not ok:
parsed = urlparse(url)
log_ssrf_block(parsed.hostname or url, reason, context="web-crawl")
return ok, reason
def get_user_agent() -> str:
"""爬取专用 User-Agent不伪装为浏览器。
url_fetcher.py 的伪装 UA 独立遵循 PRD"不伪装"原则
"""
return "YuxiCrawler/1.0 (+https://github.com/ForcePilot/yuxi)"
def should_respect_robots() -> bool:
"""是否尊重 robots.txt仅管理员可关闭。"""
return config.web_crawl_respect_robots