Graphify-Labs/graphify · error · ValueError
Blocked cloud metadata endpoint '{hostname}'. Got: {url!r}
Error message
Blocked cloud metadata endpoint '{hostname}'. Got: {url!r} What it means
ValueError from validate_url when the URL's hostname is in _BLOCKED_HOSTS - known cloud metadata endpoint names (e.g. metadata.google.internal). This is tier two of the SSRF guard: even with an http(s) scheme, metadata hostnames are refused before DNS resolution or connection.
Source
Thrown at graphify/security.py:122
"""Raise ValueError if *url* is not http or https, or targets a private/internal IP.
Blocks file://, ftp://, data:, and any other scheme that could be used
for SSRF or local file access. Also blocks requests to private/reserved
IP ranges (127.x, 10.x, 169.254.x, etc.) and cloud metadata endpoints
to prevent SSRF in cloud environments.
"""
parsed = urllib.parse.urlparse(url)
if parsed.scheme.lower() not in _ALLOWED_SCHEMES:
raise ValueError(
f"Blocked URL scheme '{parsed.scheme}' - only http and https are allowed. "
f"Got: {url!r}"
)
hostname = parsed.hostname
if hostname:
# Block known cloud metadata hostnames
if hostname.lower() in _BLOCKED_HOSTS:
raise ValueError(
f"Blocked cloud metadata endpoint '{hostname}'. "
f"Got: {url!r}"
)
# Resolve hostname and block private/reserved IP ranges
try:
infos = socket.getaddrinfo(hostname, None, socket.AF_UNSPEC, socket.SOCK_STREAM)
for info in infos:
addr = info[4][0]
ip = ipaddress.ip_address(addr)
if _ip_is_blocked(ip):
raise ValueError(
f"Blocked private/internal IP {addr} (resolved from '{hostname}'). "
f"Got: {url!r}"
)
except socket.gaierror as exc:
raise ValueError(
f"DNS resolution failed for '{hostname}': {exc}. Got: {url!r}"View on GitHub (pinned to 7fe58b0b0f)
Solutions
- If this is your own service: treat the block as correct - do not proxy metadata endpoints; remove the URL from config.
- If triggered by user input: return a 4xx and log the attempt (potential SSRF probe).
- For cloud config that genuinely needs metadata, use the cloud SDK/IMDS client on the instance itself, not the URL fetcher.
Example fix
# before url = cfg['health_check_url'] # 'http://metadata.google.internal/computeMetadata/v1/' fetch(url) # ValueError: Blocked cloud metadata endpoint # after url = 'https://real-service.internal/healthz' # use a routable endpoint fetch(validate_url(url))
Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
BLOCKED = {"metadata.google.internal", "instance-data"} # mirror your guard's set
if (urlparse(url).hostname or "").lower() in BLOCKED:
raise HTTPBadRequest("metadata endpoints are not allowed") Type guard
def is_safe_url(url: str) -> bool:
try:
validate_url(url)
return True
except ValueError:
return False Try / catch
try:
safe = validate_url(url)
except ValueError as exc:
if "Blocked cloud metadata" in str(exc):
log.security("SSRF attempt? url=%r", url)
return forbidden(str(exc))
raise Prevention
- Audit URL-accepting endpoints for metadata-hostname handling; blocks like this should return 4xx with audit logs.
- Keep the blocked-host list in sync with your cloud provider's metadata service names.
- Never disable SSRF guards to 'unblock' internal tooling - restructure the call instead.
When it happens
Trigger: validate_url(url) where parsed.hostname.lower() is in the _BLOCKED_HOSTS set (security.py:118-122). Any http://metadata.google.internal/... style URL from user input or config hits this immediately.
Common situations: SSRF probing of an app that accepts URLs (attack traffic); misconfigured service templates pointing at metadata names; testing scripts copied from cloud docs that use metadata hostnames as examples; proxy configs that forward metadata names.
Related errors
- Blocked URL scheme '{parsed.scheme}' - only http and https a
- ingest: {exc}
- Blocked private/internal IP {addr} (resolved from '{hostname
- OLLAMA_BASE_URL points at a link-local/metadata address ({ho
- DNS resolution failed for '{hostname}': {exc}. Got: {url!r}
AI-assisted analysis of Graphify-Labs/graphify@7fe58b0b0f (2026-08-14).
Data as JSON: /api/errors/7b688811ce76db9d.
Report an issue: GitHub.