2026-06-13 18:22:38 +08:00
|
|
|
|
"""URL validation utilities (backed by net_security.SSRFValidator)."""
|
2026-01-29 21:08:43 +08:00
|
|
|
|
|
2026-01-27 15:42:48 +08:00
|
|
|
|
import os
|
|
|
|
|
|
|
2026-06-13 18:22:38 +08:00
|
|
|
|
from yuxi.utils.net_security import SSRFPolicy, SSRFValidator
|
|
|
|
|
|
|
2026-01-27 15:42:48 +08:00
|
|
|
|
YUXI_URL_WHITELIST_ENV = "YUXI_URL_WHITELIST"
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-06-13 18:22:38 +08:00
|
|
|
|
def _get_policy_from_env() -> SSRFPolicy:
|
|
|
|
|
|
"""从环境变量构建策略(兼容 YUXI_URL_WHITELIST)。"""
|
|
|
|
|
|
whitelist = [d.strip() for d in os.environ.get(YUXI_URL_WHITELIST_ENV, "").split(",") if d.strip()]
|
|
|
|
|
|
return SSRFPolicy(allowed_domains=whitelist)
|
2026-01-27 15:42:48 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def validate_url(url: str) -> tuple[bool, str]:
|
2026-06-13 18:22:38 +08:00
|
|
|
|
"""Validate if a URL is allowed (sync wrapper).
|
2026-01-27 15:42:48 +08:00
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
url: The URL to validate.
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
A tuple of (is_valid, error_message).
|
|
|
|
|
|
If is_valid is True, error_message will be empty.
|
|
|
|
|
|
"""
|
|
|
|
|
|
if not url:
|
|
|
|
|
|
return False, "URL cannot be empty"
|
|
|
|
|
|
|
2026-06-13 18:22:38 +08:00
|
|
|
|
# 白名单为空时,URL 抓取功能禁用(保持原有行为)
|
|
|
|
|
|
if not is_url_parsing_enabled():
|
2026-01-27 15:42:48 +08:00
|
|
|
|
return False, "URL parsing feature is disabled"
|
|
|
|
|
|
|
2026-06-13 18:22:38 +08:00
|
|
|
|
validator = SSRFValidator(_get_policy_from_env())
|
|
|
|
|
|
allowed, reason = validator.validate_url_sync(url)
|
|
|
|
|
|
if not allowed:
|
|
|
|
|
|
return False, reason
|
|
|
|
|
|
return True, ""
|
2026-01-27 15:42:48 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_url_parsing_enabled() -> bool:
|
|
|
|
|
|
"""Check if URL parsing is enabled (whitelist is configured)."""
|
2026-06-13 18:22:38 +08:00
|
|
|
|
return bool(os.environ.get(YUXI_URL_WHITELIST_ENV, "").strip())
|
2026-01-27 15:42:48 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_whitelist_info() -> dict:
|
|
|
|
|
|
"""Get information about the current whitelist configuration."""
|
2026-06-13 18:22:38 +08:00
|
|
|
|
whitelist = [d.strip() for d in os.environ.get(YUXI_URL_WHITELIST_ENV, "").split(",") if d.strip()]
|
2026-01-27 15:42:48 +08:00
|
|
|
|
return {
|
|
|
|
|
|
"enabled": len(whitelist) > 0,
|
|
|
|
|
|
"domains": whitelist,
|
|
|
|
|
|
"count": len(whitelist),
|
|
|
|
|
|
}
|