iflytek/astron-agent · error · OutboundPolicyError
Outbound hostname is invalid
Error message
Outbound hostname is invalid
What it means
OutboundPolicyError from _normalize_hostname when the given hostname fails yarl's URL.build() host validation (TypeError/ValueError/UnicodeError). It guarantees every hostname checked by the SSRF guard is a syntactically valid host before IP/allow-list evaluation.
Solutions
- Fix the source URL so its host is a valid DNS name or IP (no spaces, underscores, brackets, or stray port).
- If handling internationalized domains, pre-encode them to punycode (IDNA) before validation.
- Check upstream parsing code that extracts the hostname — it may be grabbing too much or too little of the URL.
- Catch OutboundPolicyError at the plugin boundary and surface a clear 'invalid target host' message to the caller.
Example fix
// before url = "http://my_server space.internal/api" await validate_url(url) # underscore+space host // after url = "http://my-server-space.internal/api" await validate_url(url)
Defensive patterns
Strategy: validation
Validate before calling
from yarl import URL
def is_valid_host(value) -> bool:
if not isinstance(value, str) or not value.strip():
return False
try:
return bool(URL.build(scheme="http", host=value.strip().lower().rstrip(".")).raw_host)
except (TypeError, ValueError, UnicodeError):
return False Type guard
def is_str_hostname(v) -> bool:
return isinstance(v, str) and bool(v.strip()) and " " not in v and ";" not in v Try / catch
try:
await validate_url(target)
except OutboundPolicyError as exc:
logger.warning("Blocked invalid outbound URL %r: %s", target, exc)
return ToolResult(error="invalid target host") Prevention
- Extract hosts with a URL parser, not string splitting
- Punycode-encode internationalized domains before validation
- Reject hosts with underscores/spaces at input time
When it happens
Trigger: validate_url, create_socket_factory, _origin, or _parse_domains pass a hostname that URL.build(scheme='http', host=value) rejects: illegal characters, IDN/Unicode encoding failures, or a value that isn't a string (TypeError).
Common situations: A tool config or plugin passes a URL whose host contains spaces/underscores/brackets, non-ASCII domains that fail IDNA, or code extracts a host incorrectly (e.g. includes port or path in the host variable).
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- Remote resource hostname is invalid
- HTTPClientError
- MODEL_URL_CHECK_FAILED
- MODEL_URL_CHECK_FAILED
- MODEL_URL_ILLEGAL_FAILED
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/da007fbb4bd0cf0a.
Report an issue: GitHub.
Appendix: source
Thrown at core/plugin/link/infra/tool_exector/ssrf_guard.py:282
"PRIVATE_ENDPOINT_ALLOW_LIST entries must not include params or a query"
)
endpoints.append(_endpoint(parsed))
return tuple(endpoints)
def _endpoint(parsed: SplitResult) -> Endpoint:
scheme, hostname, port = _origin(parsed.geturl())
return scheme, hostname, port, parsed.path or "/"
def _normalize_hostname(hostname: str) -> str:
value = hostname.strip().lower().rstrip(".")
if _parse_ip(value) is not None:
return value
try:
normalized = URL.build(scheme="http", host=value).raw_host
except (TypeError, ValueError, UnicodeError) as exc:
raise OutboundPolicyError("Outbound hostname is invalid") from exc
if not normalized:
raise OutboundPolicyError("Outbound hostname is invalid")
return normalized.rstrip(".")
def _parse_ip(value: str) -> Union[IpAddress, None]:
try:
return ipaddress.ip_address(value)
except ValueError:
return None
def _matches_any(address: IpAddress, networks: Tuple[IpNetwork, ...]) -> bool:
candidates: Tuple[IpAddress, ...] = (address,)
if isinstance(address, ipaddress.IPv6Address) and address.ipv4_mapped:
candidates += (address.ipv4_mapped,)
return any(
candidate.version == network.version and candidate in networkView on GitHub (pinned to 5e758547a8)