fix: Allow HTTP for all private network ranges in Supabase URLs (#417)

* fix: Allow HTTP for all private network ranges in Supabase URLs

- Extend HTTP support to all RFC 1918 private IP ranges
- Class A: 10.0.0.0 to 10.255.255.255 (10.0.0.0/8)
- Class B: 172.16.0.0 to 172.31.255.255 (172.16.0.0/12)
- Class C: 192.168.0.0 to 192.168.255.255 (192.168.0.0/16)
- Also includes link-local (169.254.0.0/16) addresses
- Uses Python's ipaddress module for robust IP validation
- Maintains HTTPS requirement for public/production URLs
- Backwards compatible with existing localhost exceptions

* security: Fix URL validation vulnerabilities

- Replace substring matching with exact hostname matching to prevent bypass attacks
- Exclude unspecified address (0.0.0.0) from allowed HTTP hosts
- Add support for .localhost domains per RFC 6761
- Improve error messages with hostname context for better debugging

Addresses security concerns raised in PR review regarding:
- Malicious domains like 'localhost.attacker.com' bypassing HTTPS requirements
- Unspecified address being incorrectly allowed as valid connection target

---------

Co-authored-by: tazmon95 <tazmon95@users.noreply.github.com>
Co-authored-by: root <root@supatest2.jtpa.net>
This commit is contained in:
John C Fitzpatrick 2025-08-21 11:06:25 -07:00 committed by GitHub
parent 6f7c08eeb7
commit eb526af689
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -3,6 +3,7 @@ Environment configuration management for the MCP server.
"""
import os
import ipaddress
from dataclasses import dataclass
from urllib.parse import urlparse
@ -104,8 +105,29 @@ def validate_supabase_url(url: str) -> bool:
# Require HTTPS for production (non-local) URLs
if parsed.scheme == "http":
hostname = parsed.hostname or ""
if not any(local in hostname for local in ["localhost", "127.0.0.1", "host.docker.internal", "0.0.0.0"]):
raise ConfigurationError("Supabase URL must use HTTPS for non-local environments")
# Check for exact localhost and Docker internal hosts (security: prevent subdomain bypass)
local_hosts = ["localhost", "127.0.0.1", "host.docker.internal"]
if hostname in local_hosts or hostname.endswith(".localhost"):
return True
# Check if hostname is a private IP address
try:
ip = ipaddress.ip_address(hostname)
# Allow HTTP for private IP addresses (RFC 1918)
# Class A: 10.0.0.0/8
# Class B: 172.16.0.0/12
# Class C: 192.168.0.0/16
# Also includes link-local (169.254.0.0/16) and loopback
# Exclude unspecified address (0.0.0.0) for security
if (ip.is_private or ip.is_loopback or ip.is_link_local) and not ip.is_unspecified:
return True
except ValueError:
# hostname is not a valid IP address, could be a domain name
pass
# If not a local host or private IP, require HTTPS
raise ConfigurationError(f"Supabase URL must use HTTPS for non-local environments (hostname: {hostname})")
if not parsed.netloc:
raise ConfigurationError("Invalid Supabase URL format")