iflytek/astron-agent · error · RemoteResourcePolicyError
Remote resource URL must not include user information
Error message
Remote resource URL must not include user information
What it means
_validate_parsed_resource_url rejects URLs containing userinfo (user:password@host). Embedding credentials in the URL is both a credential-leak risk (logged, proxied) and a parser-differential SSRF vector (browsers and servers may disagree on where the host begins), so the library refuses such URLs.
Solutions
- Remove credentials from the URL; authenticate via presigned query parameters or headers instead.
- Use a public, unauthenticated URL for the resource.
- If the upstream requires basic auth, fetch it yourself with an authenticated aiohttp/httpx call rather than this SSRF-guarded downloader.
Example fix
// before
await fetch_public_resource("https://user:pass@files.example.com/report.pdf")
// after
await fetch_public_resource("https://files.example.com/signed/report.pdf?token=...") Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlsplit p = urlsplit(url) assert p.username is None and p.password is None, "strip credentials from URL"
Type guard
def is_credential_free(u):
try:
p = urlsplit(u)
return p.username is None and p.password is None
except (TypeError, ValueError):
return False Try / catch
try:
data = await fetch_public_resource(url)
except HTTPClientException as e:
if "user information" in str(e):
... # strip credentials, use presigned URL instead Prevention
- Never embed basic-auth in URLs; use signed URLs or headers
- Reject '@' in netloc during input validation
- Rotate any credentials previously embedded in URLs
When it happens
Trigger: URL like 'https://user:pass@files.example.com/file' or 'http://admin@host/x' — parsed.username or parsed.password is not None.
Common situations: Old-style basic-auth-in-URL object storage links; copy-pasted URLs from tools that embed tokens in the authority; attempts to smuggle a different host via 'https://evil.com\@good.com/' style payloads.
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
- Only HTTP and HTTPS remote resources are allowed
- TOOLBOX_URL_ILLEGAL
- TOOLBOX_URL_SHORT_NOT_SUPPORTED
- Tool path must not change the endpoint origin
- Outbound URL must not include user information
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/006429e8ad875516.
Report an issue: GitHub.
Appendix: source
Thrown at core/plugin/aitools/common/clients/safe_download.py:215
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 value
try:
normalized = URL.build(scheme="http", host=value).raw_hostView on GitHub (pinned to 5e758547a8)