From 676d48ea1f9680eb6f4c2c26ee6d4ac091e8abbf Mon Sep 17 00:00:00 2001 From: HackWeasel Date: Mon, 15 Dec 2025 16:12:28 -0500 Subject: [PATCH] fix: allow Docker networking hostnames in SSRF check for local Ollama MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SSRF protection was blocking endpoint tests for Ollama because host.docker.internal and ollama-host resolve to private IPs. These Docker networking hostnames are now allowlisted: - host.docker.internal (Docker's standard for reaching host) - ollama-host (custom alias defined in docker-compose) - gateway.docker.internal (Docker gateway) This enables Community Edition users to test local Ollama endpoints while maintaining SSRF protection against other private IP access. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- apps/control-panel-backend/app/api/v1/models.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/control-panel-backend/app/api/v1/models.py b/apps/control-panel-backend/app/api/v1/models.py index e9eba24..dd818c1 100644 --- a/apps/control-panel-backend/app/api/v1/models.py +++ b/apps/control-panel-backend/app/api/v1/models.py @@ -30,15 +30,31 @@ def is_private_ip(url: str) -> bool: SSRF Protection: Prevents requests to private networks (RFC1918), localhost, loopback, and other reserved IP ranges. Also resolves hostnames to check if they point to private IPs. + + Exception: Docker networking hostnames (host.docker.internal, ollama-host) + are allowed for Community Edition local deployments where services + need to reach the host machine from within containers. """ import socket + # Docker networking hostnames allowed for local model access (Ollama, vLLM, etc.) + # These only work inside Docker containers and are explicitly configured in docker-compose + DOCKER_ALLOWED_HOSTS = { + 'host.docker.internal', # Docker's standard for reaching host (macOS/Windows/Linux) + 'ollama-host', # Custom alias for Ollama defined in docker-compose + 'gateway.docker.internal', # Docker gateway (sometimes used) + } + try: parsed = urlparse(url) hostname = parsed.hostname if not hostname: return True + # Allow Docker networking hostnames for local model access + if hostname.lower() in DOCKER_ALLOWED_HOSTS: + return False + # Check for localhost variants if hostname in ('localhost', '127.0.0.1', '::1', '0.0.0.0', '0', 'localhost.localdomain'): return True