lfnovo/open-notebook · critical · ValueError
Link-local addresses (169.254.x.x) are not allowed for secur
Error message
Link-local addresses (169.254.x.x) are not allowed for security reasons. These addresses are used for cloud metadata endpoints.
What it means
The URL contained a literal link-local IP (169.254.x.x, fe80::/10, or an IPv4-mapped form like ::ffff:169.254.169.254) rather than a hostname. Because these addresses serve cloud metadata endpoints, they are unconditionally rejected regardless of how they were written. The 'resolved' variant of the message is used when the value came from DNS; this one fires for direct literals.
Source
Thrown at open_notebook/utils/url_validation.py:231
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:
raise ValueError(
f"Hostname '{hostname}' resolves to the AWS IMDSv6 metadata address "
"(fd00:ec2::254), which is not allowed for security reasons."
)
raise ValueError(View on GitHub (pinned to a7de90d38a)
Solutions
- Use the real service endpoint instead of the link-local metadata address
- If writing tests, assert that ValueError is raised — don't try to make the call succeed
Defensive patterns
Strategy: validation
Validate before calling
import ipaddress
from urllib.parse import urlparse
def is_literal_link_local(url: str) -> bool:
host = urlparse(url).hostname or ""
try:
ip = ipaddress.ip_address(host)
except ValueError:
return False
return ip.is_link_local or (ip.version == 6 and int(ip) == int(ipaddress.IPv6Address("::ffff:169.254.169.254"))) Try / catch
try:
validate_url(url)
except ValueError as e:
if "Link-local" in str(e):
return {"allowed": False, "reason": "cloud-metadata-blocked"}
raise Prevention
- Block literal link-local IPs at the form layer for faster feedback
- In tests, assert the block rather than trying to bypass it
When it happens
Trigger: Passing 'http://169.254.169.254/latest/meta-data/' or 'http://[fe80::1]/' directly as a base_url to validate_url or prepare_pinned_http_target (and thus to any discover/connection-test call).
Common situations: SSRF probing of instance metadata; debugging scripts that copied the metadata endpoint; test suites deliberately probing the guardrail.
Related errors
- Hostname '{hostname}' resolves to a link-local address (169.
- 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/0e385601b601dafb.
Report an issue: GitHub.