
    i                         d Z ddlZddlZddlZddlmZ  ej        e          Z e	ddh          Z
 ej        d          Zdej        ej        z  defd	Zd
edefdZdS )u  URL safety checks — blocks requests to private/internal network addresses.

Prevents SSRF (Server-Side Request Forgery) where a malicious prompt or
skill could trick the agent into fetching internal resources like cloud
metadata endpoints (169.254.169.254), localhost services, or private
network hosts.

Limitations (documented, not fixable at pre-flight level):
  - DNS rebinding (TOCTOU): an attacker-controlled DNS server with TTL=0
    can return a public IP for the check, then a private IP for the actual
    connection. Fixing this requires connection-level validation (e.g.
    Python's Champion library or an egress proxy like Stripe's Smokescreen).
  - Redirect-based bypass is mitigated by httpx event hooks that re-validate
    each redirect target in vision_tools, gateway platform adapters, and
    media cache helpers. Web tools use third-party SDKs (Firecrawl/Tavily)
    where redirect handling is on their servers.
    N)urlparsezmetadata.google.internalzmetadata.googz100.64.0.0/10ipreturnc                 x    | j         s| j        s| j        s| j        rdS | j        s| j        rdS | t          v rdS dS )z<Return True if the IP should be blocked for SSRF protection.TF)
is_privateis_loopbackis_link_localis_reservedis_multicastis_unspecified_CGNAT_NETWORK)r   s    8/home/agentuser/.hermes/hermes-agent/tools/url_safety.py_is_blocked_ipr   '   s[    	}  "*: bn t	 "+ t	^t5    urlc                    	 t          |           }|j        pd                                                                }|sdS |t          v rt
                              d|           dS 	 t          j        |dt          j	        t          j
                  }n1# t          j        $ r t
                              d|           Y dS w xY w|D ]d\  }}}}}|d         }	 t          j        |          }n# t          $ r Y 2w xY wt          |          rt
                              d||            dS edS # t           $ r'}	t
                              d	| |	           Y d}	~	dS d}	~	ww xY w)
zReturn True if the URL target is not a private/internal address.

    Resolves the hostname to an IP and checks against private ranges.
    Fails closed: DNS errors and unexpected exceptions block the request.
     Fz(Blocked request to internal hostname: %sNu1   Blocked request — DNS resolution failed for: %sr   z5Blocked request to private/internal address: %s -> %sTu5   Blocked request — URL safety check error for %s: %s)r   hostnamestriplower_BLOCKED_HOSTNAMESloggerwarningsocketgetaddrinfo	AF_UNSPECSOCK_STREAMgaierror	ipaddress
ip_address
ValueErrorr   	Exception)
r   parsedr   	addr_infofamily_sockaddrip_strr   excs
             r   is_safe_urlr*   3   s   (#O)r002288:: 	5 )))NNExPPP5	*8T6;KVM_``II 	 	 	 NNNPXYYY55		 *3 	 	%FAq!Xa[F)&11    b!! Kf   uu t    	NPSUXYYYuuuuu	sk   >D/ $D/ )+B D/ *C?D/ CD/ C.-D/ .
C;8D/ :C;;/D/ ,D/ /
E 9EE )__doc__r   loggingr   urllib.parser   	getLogger__name__r   	frozensetr   
ip_networkr   IPv4AddressIPv6Addressboolr   strr*    r   r   <module>r7      s    $       ! ! ! ! ! !		8	$	$ Y     &%o66	y,y/DD 	 	 	 	 	.S .T . . . . . .r   