Security fixes
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
"""
|
||||
Security utilities for Funguy Bot plugins.
|
||||
"""
|
||||
|
||||
import ipaddress
|
||||
import socket
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger("security_utils")
|
||||
|
||||
# Networks considered unsafe for outbound connections
|
||||
PRIVATE_RANGES = [
|
||||
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'), # link‑local
|
||||
ipaddress.ip_network('0.0.0.0/8'), # "this" network
|
||||
ipaddress.ip_network('::1/128'), # IPv6 loopback
|
||||
ipaddress.ip_network('fc00::/7'), # unique local
|
||||
ipaddress.ip_network('fe80::/10'), # link‑local
|
||||
ipaddress.ip_network('::/128'), # unspecified
|
||||
]
|
||||
|
||||
def is_public_destination(target: str) -> bool:
|
||||
"""
|
||||
Returns True if `target` (hostname or IP) does NOT resolve to any
|
||||
private, loopback, or link‑local address.
|
||||
"""
|
||||
try:
|
||||
# Try parsing as an IP address first
|
||||
addr = ipaddress.ip_address(target)
|
||||
if any(addr in net for net in PRIVATE_RANGES):
|
||||
return False
|
||||
return True
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Resolve hostname to IPs
|
||||
try:
|
||||
addrinfo = socket.getaddrinfo(target, None)
|
||||
for _, _, _, _, sockaddr in addrinfo:
|
||||
ip = sockaddr[0]
|
||||
addr = ipaddress.ip_address(ip)
|
||||
if any(addr in net for net in PRIVATE_RANGES):
|
||||
return False
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f"Cannot resolve {target}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# No‑op command handler – prevents bot crash because funguy.py calls
|
||||
# handle_command() on every module in the plugins directory.
|
||||
# ---------------------------------------------------------------------------
|
||||
async def handle_command(room, message, bot, prefix, config):
|
||||
"""This module is not a command plugin; ignore all messages."""
|
||||
pass
|
||||
Reference in New Issue
Block a user