mirror of
https://github.com/Rarebuffalo/securelens-backend.git
synced 2026-06-19 07:00:30 +00:00
47 lines
1.5 KiB
Python
47 lines
1.5 KiB
Python
import ipaddress
|
|
import socket
|
|
from urllib.parse import urlparse
|
|
|
|
from fastapi import HTTPException
|
|
|
|
PRIVATE_NETWORKS = [
|
|
ipaddress.ip_network("10.0.0.0/8"),
|
|
ipaddress.ip_network("172.16.0.0/12"),
|
|
ipaddress.ip_network("192.168.0.0/16"),
|
|
ipaddress.ip_network("127.0.0.0/8"),
|
|
ipaddress.ip_network("169.254.0.0/16"),
|
|
ipaddress.ip_network("0.0.0.0/8"),
|
|
ipaddress.ip_network("::1/128"),
|
|
ipaddress.ip_network("fc00::/7"),
|
|
ipaddress.ip_network("fe80::/10"),
|
|
]
|
|
|
|
|
|
def validate_url(url: str) -> str:
|
|
parsed = urlparse(url)
|
|
|
|
if parsed.scheme not in ("http", "https"):
|
|
raise HTTPException(status_code=400, detail="URL must use http or https scheme")
|
|
|
|
hostname = parsed.hostname
|
|
if not hostname:
|
|
raise HTTPException(status_code=400, detail="Invalid URL: no hostname found")
|
|
|
|
blocked_hostnames = {"localhost", "0.0.0.0"}
|
|
if hostname in blocked_hostnames:
|
|
raise HTTPException(status_code=400, detail="Scanning internal addresses is not allowed")
|
|
|
|
try:
|
|
resolved_ip = socket.gethostbyname(hostname)
|
|
ip = ipaddress.ip_address(resolved_ip)
|
|
for network in PRIVATE_NETWORKS:
|
|
if ip in network:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail="Scanning internal/private IP addresses is not allowed",
|
|
)
|
|
except socket.gaierror:
|
|
raise HTTPException(status_code=400, detail=f"Could not resolve hostname: {hostname}")
|
|
|
|
return url
|