langchain-ai/langchain · critical · SSRFBlockedError
cloud metadata endpoint
Error message
cloud metadata endpoint
What it means
`"cloud metadata endpoint"` is the reason raised via `validate_resolved_ip`'s `raise SSRFBlockedError(reason)` when the resolved IP is the link-local cloud instance-metadata address (169.254.169.254, or `fd00:ec2::254` for IPv6) and `block_cloud_metadata` is on. That endpoint hands out cloud credentials (IAM roles on AWS/GCP/Azure), making it the highest-value SSRF target; the guard blocks any attempt to fetch it.
Source
Thrown at libs/core/langchain_core/_security/_policy.py:212
def validate_resolved_ip(ip_str: str, policy: SSRFPolicy) -> None:
"""Validate a resolved IP address against the SSRF policy.
Raises SSRFBlockedError if the IP is blocked.
"""
try:
addr = ipaddress.ip_address(ip_str)
except ValueError as exc:
msg = "invalid IP address"
raise SSRFBlockedError(msg) from exc
if isinstance(addr, ipaddress.IPv6Address):
inner = _extract_embedded_ipv4(addr)
if inner is not None:
addr = inner
reason = _ip_in_blocked_networks(addr, policy)
if reason is not None:
raise SSRFBlockedError(reason)
def validate_hostname(hostname: str, policy: SSRFPolicy) -> None:
"""Validate a hostname against the SSRF policy.
Raises SSRFBlockedError if the hostname is blocked.
"""
lower = hostname.lower()
if policy.block_localhost and lower in _LOCALHOST_NAMES:
msg = "localhost address"
raise SSRFBlockedError(msg)
if policy.block_cloud_metadata and lower in _CLOUD_METADATA_HOSTNAMES:
msg = "cloud metadata endpoint"
raise SSRFBlockedError(msg)
if policy.block_k8s_internal and lower.endswith(_K8S_SUFFIX):View on GitHub (pinned to e32fa9a52e)
Solutions
- Never disable `block_cloud_metadata` for user- or model-supplied URLs.
- If a legitimate hostname resolves to 169.254.169.254, fix the DNS/VPC configuration — that resolution itself is the anomaly.
- For tests, use `allowed_hosts` with a benign name rather than the literal metadata address.
Example fix
# before
await validate_url('http://169.254.169.254/latest/meta-data/', DEFAULT_SSRF_POLICY)
# SSRFBlockedError: cloud metadata endpoint
# after — never allowlist this; restrict fetch sources by scheme/host instead
policy = SSRFPolicy(allowed_hosts={'api.trusted.example'})
await validate_url('https://api.trusted.example/data', policy) Defensive patterns
Strategy: try-catch
Validate before calling
# Defensive pre-check: never let metadata IPs near the fetch layer
import ipaddress
METADATA_IPS = {ipaddress.ip_address("169.254.169.254")}
def looks_like_metadata(url: str) -> bool:
host = urlparse(url).hostname or ""
try:
return ipaddress.ip_address(host) in METADATA_IPS
except ValueError:
return host in {"metadata.google.internal", "metadata"} Try / catch
from langchain_core._security._policy import SSRFBlockedError
try:
await validate_url(url, policy)
except SSRFBlockedError as e:
if "cloud metadata" in str(e):
alert_security(url) # treat as attempted credential access
raise Prevention
- Never allowlist 169.254.169.254 or metadata hostnames in any policy.
- Fetch cloud credentials via the provider SDK credential chain, not HTTP fetch tools.
- Alert on this block, don't just log it — it frequently indicates prompt injection.
When it happens
Trigger: `await validate_url('http://169.254.169.254/latest/meta-data/iam/...')`, or any hostname that DNS-resolves to 169.254.169.254, under the default policy with `block_cloud_metadata=True`. Also hit indirectly when a misconfigured internal DNS wildcard resolves an arbitrary name to the link-local address.
Common situations: Agent/tool workflows that accept model-chosen URLs: a prompt-injected model tries to read the instance metadata to exfiltrate credentials. Benign collisions are rare but happen with link-local network diagnostics or when testing SSRF rules themselves. In production this error on a legitimate fetch almost always means DNS is resolving your service name to the metadata IP — investigate, don't bypass.
Related errors
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/72413f00c7e82f49.
Report an issue: GitHub.