iflytek/astron-agent · error · OutboundPolicyError
Only HTTP and HTTPS tool URLs are allowed
Error message
Only HTTP and HTTPS tool URLs are allowed
What it means
The SSRF guard only permits http and https schemes for outbound tool requests. Any other scheme (file:, ftp:, gopher:, dict:, ws:) is rejected because non-HTTP schemes can be used to reach local files or internal services in SSRF attacks.
Solutions
- Use http:// or https:// explicitly in the configured tool URL.
- If the URL has no scheme, prepend https:// before passing it to the plugin.
- Fix the tool/plugin configuration value; only HTTP(S) endpoints are supported by policy.
- If another protocol is genuinely needed, it is blocked by design — route through an allowed HTTP gateway instead.
Example fix
// before url = "ftp://files.example.com/data" // after url = "https://files.example.com/data"
Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlsplit
ALLOWED = {"http", "https"}
def has_allowed_scheme(url: str) -> bool:
return urlsplit(url).scheme.lower() in ALLOWED Try / catch
try:
client.get(url)
except OutboundPolicyError:
url = "https://" + url # only if scheme was missing
client.get(url) Prevention
- Store full http(s):// URLs in configuration, never scheme-less or file:// values
- Normalize config URLs once at startup, not per-request
- Treat non-HTTP protocols as blocked by policy; use an HTTP gateway
When it happens
Trigger: _parse_http_url receives a URL whose lowercased parsed scheme is not in _ALLOWED_SCHEMES — e.g. file:///etc/passwd, ftp://host/x, or a scheme-less string like example.com/path where urlsplit yields an empty scheme.
Common situations: Tool endpoint configured as file:// or ftp://; URL built by concatenation losing the scheme; scheme-less address given where a full http(s) URL is required.
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
- HTTPClientError
- MODEL_URL_CHECK_FAILED
- MODEL_URL_CHECK_FAILED
- MODEL_URL_ILLEGAL_FAILED
- Outbound URL authority is invalid
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/69c3a131e1fdf04a.
Report an issue: GitHub.
Appendix: source
Thrown at core/plugin/link/infra/tool_exector/ssrf_guard.py:202
raise OutboundPolicyError("Outbound URL is malformed")
_validate_url_characters(url)
try:
parsed = urlsplit(url)
port = parsed.port
except (TypeError, ValueError) as exc:
raise OutboundPolicyError("Outbound URL is malformed") from exc
_validate_parsed_http_url(parsed, port)
return parsed
def _validate_url_characters(url: str) -> None:
if any(ord(character) < 0x20 or ord(character) == 0x7F for character in url):
raise OutboundPolicyError("Outbound URL contains control characters")
def _validate_parsed_http_url(parsed: SplitResult, port: Union[int, None]) -> None:
if parsed.scheme.lower() not in _ALLOWED_SCHEMES:
raise OutboundPolicyError("Only HTTP and HTTPS tool URLs are allowed")
if not parsed.hostname:
raise OutboundPolicyError("Outbound URL must include a hostname")
if parsed.username is not None or parsed.password is not None:
raise OutboundPolicyError("Outbound URL must not include user information")
if "\\" in parsed.netloc:
raise OutboundPolicyError("Outbound URL authority is invalid")
if parsed.fragment:
raise OutboundPolicyError("Outbound URL must not include a fragment")
if port is not None and not 1 <= port <= 65535:
raise OutboundPolicyError("Outbound URL port is invalid")
def _parse_networks(raw_value: str, setting_name: str) -> Tuple[IpNetwork, ...]:
networks = []
for entry in raw_value.split(","):
value = entry.strip()
if not value:
continueView on GitHub (pinned to 5e758547a8)