17 lines
650 B
Python
17 lines
650 B
Python
import ipaddress
|
|
import socket
|
|
from urllib.parse import urlparse
|
|
|
|
|
|
def safe_public_url(url):
|
|
"""Resolve url's host and reject any that maps to a non-public IP (SSRF guard)."""
|
|
p = urlparse(url)
|
|
if p.scheme not in ("http", "https") or not p.hostname:
|
|
raise ValueError("url must be http(s) with a hostname")
|
|
for info in socket.getaddrinfo(p.hostname, None):
|
|
ip = ipaddress.ip_address(info[4][0])
|
|
if (ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved
|
|
or ip.is_multicast or ip.is_unspecified):
|
|
raise ValueError(f"host resolves to non-public ip {ip}")
|
|
return url
|