lfnovo/open-notebook · critical · ValueError
Hostname '{hostname}' resolves to a link-local address (169.
Error message
Hostname '{hostname}' resolves to a link-local address (169.254.x.x) which is not allowed for security reasons. These addresses are used for cloud metadata endpoints. What it means
A user-supplied hostname (not a raw IP) resolved via DNS to a link-local address (169.254.x.x or fe80::/10, including IPv4-mapped IPv6 forms). These ranges host cloud metadata services (AWS/GCP/Azure IMDS), so reaching them via a configurable URL is a classic SSRF vector and is blocked. The message names the hostname because it was resolved, not written literally.
Source
Thrown at open_notebook/utils/url_validation.py:226
return safe
def _reject_dangerous_ip(
ip: "ipaddress.IPv4Address | ipaddress.IPv6Address",
hostname: str,
resolved: bool = False,
) -> None:
"""Raise ValueError if `ip` is a link-local or cloud-metadata address."""
is_ipv4_mapped_link_local = (
hasattr(ip, "ipv4_mapped") and ip.ipv4_mapped and ip.ipv4_mapped.is_link_local
)
# Block link-local addresses (169.254.x.x / fe80::/10) - used for cloud
# metadata - including IPv4-mapped IPv6 addresses pointing to link-local
# (e.g. ::ffff:169.254.169.254 bypasses IPv6 is_link_local check).
if ip.is_link_local or is_ipv4_mapped_link_local:
if resolved:
raise ValueError(
f"Hostname '{hostname}' resolves to a link-local address (169.254.x.x) "
"which is not allowed for security reasons. These addresses are used "
"for cloud metadata endpoints."
)
raise ValueError(
"Link-local addresses (169.254.x.x) are not allowed for security reasons. "
"These addresses are used for cloud metadata endpoints."
)
# Block AWS's IMDSv6 metadata address - a Unique Local Address, not
# link-local, so it needs its own explicit check. Compare without scope
# ID so scoped forms (fd00:ec2::254%eth0) cannot bypass the sentinel.
is_aws_imds_v6 = (
isinstance(ip, ipaddress.IPv6Address)
and int(ip) == int(_AWS_IMDS_V6_ADDRESS)
)
if is_aws_imds_v6:
if resolved:View on GitHub (pinned to a7de90d38a)
Solutions
- Remove the hostname that resolves to 169.254.x.x from the provider config — it will never be allowed
- If you genuinely need a cloud API, use its public hostname (e.g. metrics or IMDS via the SDK's built-in mechanism), not a metadata IP
- Audit where the DNS record comes from and fix it if it was unintentional
Defensive patterns
Strategy: validation
Validate before calling
import ipaddress
def is_safe_public_target(host: str) -> bool:
try:
ip = ipaddress.ip_address(host)
except ValueError:
return True # hostname; DNS-time check still applies
return not (ip.is_link_local or ip.is_private is False and ip.is_reserved) Try / catch
try:
target = await prepare_pinned_http_target(url, provider)
except ValueError as e:
if "link-local" in str(e) or "metadata" in str(e):
log_security_event(url) # potential SSRF attempt
raise Prevention
- Never point provider URLs at 169.254.x.x or fe80::/10
- Restrict who can edit provider base_url in multi-tenant deployments
- Treat repeated metadata-endpoint attempts as security events
When it happens
Trigger: Setting a provider base_url to a hostname whose DNS resolves to 169.254.169.254 (e.g. a wildcard DNS service like nip.io/sslip.io style names, or an internal name that points at the metadata IP), then running discover_with_config or a connection test.
Common situations: Attempting to probe cloud instance metadata from the app; DNS rebinding-style SSRF tests; misconfigured internal DNS that maps a friendly name to a link-local address.
Related errors
- Link-local addresses (169.254.x.x) are not allowed for secur
- Hostname '{hostname}' resolves to the AWS IMDSv6 metadata ad
- The AWS IMDSv6 metadata address (fd00:ec2::254) is not allow
- Invalid {kind} name: {value!r}
AI-assisted analysis of lfnovo/open-notebook@a7de90d38a (2026-08-27).
Data as JSON: /api/errors/676ae4ffa5f9dbab.
Report an issue: GitHub.