iflytek/astron-agent · error · RemoteResourcePolicyError
Remote resource URL must include a hostname
Error message
Remote resource URL must include a hostname
What it means
_validate_parsed_resource_url requires a non-empty hostname. URLs whose netloc is empty or consist only of a scheme+path (e.g. 'https:///path' or 'https://file.pdf') are rejected because there is no remote host to validate against, making SSRF/destination checks impossible.
Solutions
- Include the full authority in the URL: 'https://host.example.com/path'.
- If building from parts, use urllib.parse.urljoin(base, path) with a complete absolute base URL.
- Check the config/env value supplying the base URL contains the hostname.
Example fix
// before
url = "/bucket/file.pdf" # no host
await fetch_public_resource(url)
// after
from urllib.parse import urljoin
url = urljoin("https://files.example.com", "/bucket/file.pdf")
await fetch_public_resource(url) Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlsplit assert bool(urlsplit(url).hostname), "URL must include a hostname"
Type guard
def has_hostname(u):
try:
return bool(urlsplit(u).hostname)
except (TypeError, ValueError):
return False Try / catch
try:
data = await fetch_public_resource(url)
except HTTPClientException as e:
if "hostname" in str(e):
... # fix URL construction / base-url config Prevention
- Use urljoin with an absolute base URL
- Verify configured base URLs contain the domain
- Reject path-only inputs at your API boundary
When it happens
Trigger: URL like 'https:///file' or 'http://:8080/x'; string slicing bugs that drop the host; passing a path-only string after accidentally splitting off the domain; 'https://?query=1'.
Common situations: Template concatenation bugs (f'{base}{path}' where base is empty); joining URL parts with a helper that lost the host; config value for a base URL missing the domain (e.g. OSS download host configured as just '/bucket').
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- The file address is incorrect
- Remote resource URL is malformed
- TOOLBOX_URL_ILLEGAL
- Only HTTP and HTTPS remote resources are allowed
- Remote resource URL must not include user information
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/814ba3073342b34b.
Report an issue: GitHub.
Appendix: source
Thrown at core/plugin/aitools/common/clients/safe_download.py:213
def _validate_url_characters(url: str) -> None:
if not isinstance(url, str) or any(
ord(character) < 0x20 or ord(character) == 0x7F for character in url
):
raise RemoteResourcePolicyError("Remote resource URL is malformed")
def _validate_parsed_resource_url(
parsed: SplitResult,
port: Optional[int],
) -> None:
if parsed.scheme.lower() not in _ALLOWED_SCHEMES:
raise RemoteResourcePolicyError(
"Only HTTP and HTTPS remote resources are allowed"
)
if not parsed.hostname:
raise RemoteResourcePolicyError("Remote resource URL must include a hostname")
if parsed.username is not None or parsed.password is not None:
raise RemoteResourcePolicyError(
"Remote resource URL must not include user information"
)
if "\\" in parsed.netloc:
raise RemoteResourcePolicyError("Remote resource URL authority is invalid")
if parsed.fragment:
raise RemoteResourcePolicyError(
"Remote resource URL must not include a fragment"
)
if port is not None and not 1 <= port <= 65535:
raise RemoteResourcePolicyError("Remote resource URL port is invalid")
def _normalize_hostname(hostname: str) -> str:
value = hostname.strip().lower().rstrip(".")
if _parse_ip(value) is not None:
return valueView on GitHub (pinned to 5e758547a8)