ComposioHQ/composio · error · BlockedInternalUrlError
Could not resolve host "{parsed.hostname}"
Error message
Could not resolve host "{parsed.hostname}" What it means
Raised by assert_safe_fetch_target when DNS resolution via socket.getaddrinfo returns an address entry that is not a plain string (unexpected getaddrinfo shape). It is a fail-closed guard in the SSRF-protection layer: any ambiguity in the resolved address is treated as unsafe and blocks the fetch with BlockedInternalUrlError.
Source
Thrown at python/composio/utils/url_safety.py:103
prepared_url = requests.Request(method="GET", url=url).prepare().url
if prepared_url is None:
raise ValueError("Prepared URL is missing")
parsed = urlparse(prepared_url)
if parsed.scheme not in {"http", "https"} or not parsed.hostname:
raise ValueError("URL must use HTTP(S) and include a hostname")
except (requests.exceptions.RequestException, ValueError):
raise BlockedInternalUrlError(
"Refusing to fetch a malformed or non-http(s) URL"
) from None
try:
# Resolver order is kept: it encodes the system's address preference
# (RFC 6724), and connecting walks it the way urllib3 would.
addresses: t.List[str] = []
for result in socket.getaddrinfo(parsed.hostname, None):
address = result[4][0]
if not isinstance(address, str):
raise BlockedInternalUrlError(
f'Could not resolve host "{parsed.hostname}"'
)
if address not in addresses:
addresses.append(address)
except socket.gaierror as error:
raise BlockedInternalUrlError(
f'Could not resolve host "{parsed.hostname}"'
) from error
for address in addresses:
if is_blocked_ip(address):
raise BlockedInternalUrlError(
f'Refusing to fetch "{parsed.hostname}" because it resolves to a non-public address'
)
if not addresses:
raise BlockedInternalUrlError(f'Could not resolve host "{parsed.hostname}"')
View on GitHub (pinned to 64b1b85502)
Solutions
- Verify how getaddrinfo is being mocked/patched in tests; return tuples whose result[4][0] is a string IP
- Check for socket monkey-patching (e.g. gevent, eventlet) or unusual resolver configurations
- Avoid hostnames that resolve via non-standard resolver backends when using safe_request
Defensive patterns
Strategy: try-catch
Try / catch
try:
safe_request('GET', url)
except BlockedInternalUrlError as e:
# resolution guard tripped; log and skip
log.warning('blocked fetch: %s', e) Prevention
- Avoid patching socket.getaddrinfo in processes that use safe_request
- Return string IPs from resolver mocks
When it happens
Trigger: Calling safe_request (or _pinned_request) with a URL whose hostname resolution returns a non-string sockaddr (exotic resolver/IPv6 sandbox setups). Effectively unreachable on normal CPython resolvers.
Common situations: Custom DNS resolvers, patched socket modules, or test environments mocking getaddrinfo incorrectly.
Understand the failure class
- DNS resolution errors: ENOTFOUND and getaddrinfo failures — how hostname lookups fail and how to debug them.
Related errors
- Refusing to fetch "{parsed.hostname}" because it resolves to
- Refusing to talk to "{hostname}": the connection was establi
- Could not resolve host "${host}"
- Error downloading file: {_sanitize_url_for_logging(self.s3ur
- Failed to fetch file from URL: {e.cause}
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/fce25b9d69bb6249.
Report an issue: GitHub.