unslothai/unsloth · error · ValueError

Provider base URL points at a private address, which is disa

Error message

Provider base URL points at a private address, which is disabled on this server (UNSLOTH_STUDIO_BLOCK_PRIVATE_PROVIDER_URLS=1).

What it means

Raised when UNSLOTH_STUDIO_BLOCK_PRIVATE_PROVIDER_URLS=1 and the resolved addresses of the provider base URL include a non-global IP (loopback, LAN, link-local, or an empty resolution list). This is an opt-in SSRF hardening: the backend sends the caller's decrypted API key to this URL, so private targets are refused. Plain http, odd ports, and userinfo remain allowed — only address reachability class is checked.

Source

Thrown at studio/backend/core/inference/providers.py:848

        if resolved is None:
            # This path blocked on an unbounded getaddrinfo before the metadata
            # check existed, and a resolver slower than that check's deadline is
            # ordinary (the Linux default is 5s per server, twice). Falling back
            # to the same unbounded call keeps a slow-but-working resolver from
            # turning into a refusal here, where "no answer" fails closed.
            import socket
            try:
                infos = socket.getaddrinfo(
                    _transport_host(hostname),
                    port or (443 if scheme == "https" else 80),
                    type = socket.SOCK_STREAM,
                )
            except (OSError, UnicodeError) as exc:
                raise ValueError("Provider base URL hostname could not be resolved.") from exc
            resolved = tuple(str(info[4][0]) for info in infos)
        addresses = [ipaddress.ip_address(address.split("%", 1)[0]) for address in resolved]
    if not addresses or any(not ip.is_global for ip in addresses):
        raise ValueError(
            "Provider base URL points at a private address, which is disabled on this "
            f"server ({_BLOCK_PRIVATE_ENV}=1)."
        )


def validate_provider_base_url(base_url: str) -> str:
    """Return a normalized provider base URL, or raise ``ValueError``.

    The backend issues outbound requests to this URL with the caller's decrypted
    API key attached, so it is caller-controlled server-side egress. Only shapes
    that can never be a real provider endpoint are refused: a non-http(s) scheme,
    control characters, a missing host, and cloud metadata services. Plain http,
    loopback, LAN hosts, odd ports, query strings and basic-auth userinfo all
    stay valid -- Ollama, llama.cpp, vLLM and custom gateways rely on them. A
    caller-supplied hostname is resolved far enough to apply the metadata block
    to DNS aliases of it; rejecting other private addresses stays opt-in.

    Normalization is strip + trailing-slash removal only (what the client did

View on GitHub (pinned to 203007d190)

Solutions

  1. If the private endpoint is intentional and trusted, unset UNSLOTH_STUDIO_BLOCK_PRIVATE_PROVIDER_URLS (or set to 0) — the check is explicitly opt-in.
  2. Otherwise point the base URL at a genuinely public provider endpoint.
  3. If a public hostname resolves privately (split-horizon DNS), use an endpoint that resolves publicly from this host.
  4. Document which environments run with the flag on so LAN gateways are not configured there.

Example fix

# before (flag on, LAN gateway refused)
validate_provider_base_url("http://192.168.1.10:11434/v1")
# after (trust the LAN gateway)
# export UNSLOTH_STUDIO_BLOCK_PRIVATE_PROVIDER_URLS=0
validate_provider_base_url("http://192.168.1.10:11434/v1")
Defensive patterns

Strategy: validation

Validate before calling

import ipaddress, socket, os

def url_is_public(url: str) -> bool:
    from urllib.parse import urlsplit
    h = urlsplit(url).hostname
    if not h:
        return False
    try:
        infos = socket.getaddrinfo(h, None, type=socket.SOCK_STREAM)
    except OSError:
        return False
    return all(ipaddress.ip_address(i[4][0]).is_global for i in infos)

Try / catch

try:
    validate_provider_base_url(url)
except ValueError as e:
    if "private address" in str(e):
        if trusted_internal_gateway(url):
            os.environ.pop("UNSLOTH_STUDIO_BLOCK_PRIVATE_PROVIDER_URLS")
            url = validate_provider_base_url(url)

Prevention

When it happens

Trigger: Setting a provider base URL to http://192.168.1.10:11434/v1 (Ollama), http://localhost:8080 (llama.cpp), or a public name that resolves to a private IP while the block env var is set to 1.

Common situations: Self-hosted studios pointing at LAN LLM servers with the hardening flag inherited from a public deployment config; DNS rebinding where a public hostname resolves internally; 169.254.x addresses.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/44b218d47810be9a. Report an issue: GitHub.