affaan-m/ECC · error · ValueError

remote import host resolves to a non-public address

Error message

remote import host resolves to a non-public address: {host}

What it means

Raised by _validate_import_url after DNS resolution when any resolved address for the hostname is private, loopback, link-local, multicast, reserved, or unspecified. This is an SSRF guard: the CLI refuses to fetch URLs whose host resolves into internal network space. It runs on every address returned by getaddrinfo, so one bad record is enough to fail.

Solutions

  1. Use a genuinely public HTTPS endpoint for the import.
  2. For local testing, host the file on a real public URL (e.g. a gist or public bucket) rather than localhost.
  3. Check what the hostname resolves to (dig/nslookup) and switch to a hostname with public records.
  4. If this is a false positive from split-horizon DNS, import the file locally via the file import path instead.

Example fix

# before
url = "http://169.254.169.254/latest/meta-data"
# after
url = "https://raw.githubusercontent.com/org/repo/main/instincts.yaml"
Defensive patterns

Strategy: validation

Validate before calling

import ipaddress, socket
infos = socket.getaddrinfo(hostname, 443)
for info in infos:
    ip = ipaddress.ip_address(info[4][0])
    if not ip.is_global:
        raise ValueError(f"non-public address: {ip}")

Try / catch

try:
    cli_import(url=source)
except ValueError as e:
    if "non-public address" in str(e):
        print("host resolves to a private/internal IP; use a public URL")

Prevention

When it happens

Trigger: Importing from https://localhost/..., https://127.0.0.1/..., https://10.x.x.x/..., https://192.168.x.x/..., https://169.254.169.254/ (cloud metadata), or a public-looking hostname that resolves to a private IP (DNS rebinding or split-horizon DNS).

Common situations: Testing against a local mock server that must now be exposed differently; internal-only URLs that were never valid for this CLI; hostnames whose DNS returns private addresses in an office network.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/68acc49e7db4b369. Report an issue: GitHub.

Appendix: source

Thrown at skills/continuous-learning-v2/scripts/instinct-cli.py:216

        addr_infos = socket.getaddrinfo(parsed.hostname, parsed.port or 443, type=socket.SOCK_STREAM)
    except socket.gaierror as exc:
        raise ValueError(f"remote import host could not be resolved: {parsed.hostname}") from exc

    for family, _, _, _, sockaddr in addr_infos:
        host = sockaddr[0]
        try:
            ip = ipaddress.ip_address(host)
        except ValueError:
            continue
        if (
            ip.is_private
            or ip.is_loopback
            or ip.is_link_local
            or ip.is_multicast
            or ip.is_reserved
            or ip.is_unspecified
        ):
            raise ValueError(f"remote import host resolves to a non-public address: {host}")

    return urllib.parse.urlunparse(parsed)


def _fetch_import_url(source: str, *, max_bytes: int = 2 * 1024 * 1024) -> str:
    """Fetch a validated remote instinct file with bounded size and timeout."""
    url = _validate_import_url(source)
    req = urllib.request.Request(url, headers={"User-Agent": "ECC-instinct-import/2"})
    with urllib.request.urlopen(req, timeout=15) as response:
        content_type = response.headers.get("Content-Type", "")
        if content_type and not any(
            allowed in content_type.lower()
            for allowed in ("text/", "markdown", "yaml", "json", "octet-stream")
        ):
            raise ValueError(f"unsupported remote content type: {content_type}")
        data = response.read(max_bytes + 1)
    if len(data) > max_bytes:
        raise ValueError(f"remote import exceeds {max_bytes} bytes")

View on GitHub (pinned to 8321021c54)