{"record":{"id":"676ae4ffa5f9dbab","repo":"lfnovo/open-notebook","slug":"hostname-hostname-resolves-to-a-link-local-add","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"open_notebook/utils/url_validation.py","lineNumber":226,"sourceCode":"    return safe\n\n\ndef _reject_dangerous_ip(\n    ip: \"ipaddress.IPv4Address | ipaddress.IPv6Address\",\n    hostname: str,\n    resolved: bool = False,\n) -> None:\n    \"\"\"Raise ValueError if `ip` is a link-local or cloud-metadata address.\"\"\"\n    is_ipv4_mapped_link_local = (\n        hasattr(ip, \"ipv4_mapped\") and ip.ipv4_mapped and ip.ipv4_mapped.is_link_local\n    )\n\n    # Block link-local addresses (169.254.x.x / fe80::/10) - used for cloud\n    # metadata - including IPv4-mapped IPv6 addresses pointing to link-local\n    # (e.g. ::ffff:169.254.169.254 bypasses IPv6 is_link_local check).\n    if ip.is_link_local or is_ipv4_mapped_link_local:\n        if resolved:\n            raise ValueError(\n                f\"Hostname '{hostname}' resolves to a link-local address (169.254.x.x) \"\n                \"which is not allowed for security reasons. These addresses are used \"\n                \"for cloud metadata endpoints.\"\n            )\n        raise ValueError(\n            \"Link-local addresses (169.254.x.x) are not allowed for security reasons. \"\n            \"These addresses are used for cloud metadata endpoints.\"\n        )\n\n    # Block AWS's IMDSv6 metadata address - a Unique Local Address, not\n    # link-local, so it needs its own explicit check. Compare without scope\n    # ID so scoped forms (fd00:ec2::254%eth0) cannot bypass the sentinel.\n    is_aws_imds_v6 = (\n        isinstance(ip, ipaddress.IPv6Address)\n        and int(ip) == int(_AWS_IMDS_V6_ADDRESS)\n    )\n    if is_aws_imds_v6:\n        if resolved:","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/lfnovo/open-notebook/blob/a7de90d38aaf18ee85fd661854d35c11e44613e2/open_notebook/utils/url_validation.py#L208-L244","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import ipaddress\n\ndef is_safe_public_target(host: str) -> bool:\n    try:\n        ip = ipaddress.ip_address(host)\n    except ValueError:\n        return True  # hostname; DNS-time check still applies\n    return not (ip.is_link_local or ip.is_private is False and ip.is_reserved)","typeGuard":null,"tryCatchPattern":"try:\n    target = await prepare_pinned_http_target(url, provider)\nexcept ValueError as e:\n    if \"link-local\" in str(e) or \"metadata\" in str(e):\n        log_security_event(url)  # potential SSRF attempt\n    raise","preventionTips":["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"],"tags":["ssrf","security","cloud-metadata","link-local"],"backgroundTag":"ssrf-metadata-endpoint-blocked","analyzedSha":"a7de90d38aaf18ee85fd661854d35c11e44613e2","analyzedAt":"2026-08-27T02:39:58.166Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}