mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-23 10:42:00 +00:00
fix(security): handle IPv6 scope IDs in URL safety checks to prevent bypass
ipaddress.ip_address() raises ValueError on IPv6 addresses with scope IDs (e.g. 'fe80::1%eth0'). Both is_always_blocked_url() and is_safe_url() silently skipped these via `except ValueError: continue`. If ALL resolved addresses for a hostname carry scope IDs, every address is skipped and the URL passes all safety checks — a potential SSRF bypass vector against link-local or metadata endpoints. Fix: - Strip the scope ID (%eth0) before parsing in both functions - is_safe_url(): fail closed (return False) with a warning log if still unparseable after stripping - is_always_blocked_url(): use continue (not return False) to preserve multi-address scanning, with a warning log Affected: tools/url_safety.py — is_always_blocked_url(), is_safe_url()
This commit is contained in:
parent
b5b8a4cd56
commit
ed966696eb
1 changed files with 8 additions and 1 deletions
|
|
@ -282,9 +282,12 @@ def is_always_blocked_url(url: str) -> bool:
|
|||
|
||||
for _family, _, _, _, sockaddr in addr_info:
|
||||
ip_str = sockaddr[0]
|
||||
if '%' in ip_str:
|
||||
ip_str = ip_str.split('%')[0]
|
||||
try:
|
||||
resolved = ipaddress.ip_address(ip_str)
|
||||
except ValueError:
|
||||
logger.warning("Unparseable IP address %r for hostname %s — skipping address", sockaddr[0], hostname)
|
||||
continue
|
||||
if resolved in _ALWAYS_BLOCKED_IPS or any(
|
||||
resolved in net for net in _ALWAYS_BLOCKED_NETWORKS
|
||||
|
|
@ -353,10 +356,14 @@ def is_safe_url(url: str) -> bool:
|
|||
|
||||
for family, _, _, _, sockaddr in addr_info:
|
||||
ip_str = sockaddr[0]
|
||||
if '%' in ip_str:
|
||||
ip_str = ip_str.split('%')[0]
|
||||
try:
|
||||
ip = ipaddress.ip_address(ip_str)
|
||||
except ValueError:
|
||||
continue
|
||||
# Still unparseable after scope ID strip — fail closed
|
||||
logger.warning("Blocked request — unparseable IP address %r for hostname %s", sockaddr[0], hostname)
|
||||
return False
|
||||
|
||||
# Always block cloud metadata IPs and link-local, even with toggle on
|
||||
if ip in _ALWAYS_BLOCKED_IPS or any(ip in net for net in _ALWAYS_BLOCKED_NETWORKS):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue