From 982deb821c19f682009fff91f3a4f7969b56c63b Mon Sep 17 00:00:00 2001 From: Kara Engelhardt Date: Tue, 9 Jun 2026 12:42:39 +0200 Subject: [PATCH] SMTP SSRF protection: Edge case handling for CGNAT and v4/v6 mapping --- src/pretix/base/email.py | 5 +++++ src/tests/base/test_mail.py | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/pretix/base/email.py b/src/pretix/base/email.py index b6a61e8a97..db3ee6299a 100644 --- a/src/pretix/base/email.py +++ b/src/pretix/base/email.py @@ -57,6 +57,8 @@ logger = logging.getLogger('pretix.base.email') T = TypeVar("T", bound=EmailBackend) +_cgnat_net = ipaddress.ip_network('100.64.0.0/10') + def test_custom_smtp_backend(backend: T, from_addr: str) -> None: try: @@ -253,12 +255,15 @@ def create_connection(address, timeout=socket.getdefaulttimeout(), if not getattr(settings, "MAIL_CUSTOM_SMTP_ALLOW_PRIVATE_NETWORKS", False): ip_addr = ipaddress.ip_address(sa[0]) + check_ip4 = ip_addr.ipv4_mapped if getattr(ip_addr, "ipv4_mapped", None) else ip_addr if ip_addr.is_multicast: raise socket.error(f"Request to multicast address {sa[0]} blocked") if ip_addr.is_loopback or ip_addr.is_link_local: raise socket.error(f"Request to local address {sa[0]} blocked") if ip_addr.is_private: raise socket.error(f"Request to private address {sa[0]} blocked") + if check_ip4 in _cgnat_net: + raise socket.error(f"Request to RFC 6598 address {sa[0]} blocked") sock = None try: diff --git a/src/tests/base/test_mail.py b/src/tests/base/test_mail.py index 581710f48e..9a5a9e66a4 100644 --- a/src/tests/base/test_mail.py +++ b/src/tests/base/test_mail.py @@ -602,10 +602,13 @@ PRIVATE_IPS_RES = [ [(socket.AF_INET, socket.SOCK_STREAM, 6, '', ('127.1.1.1', 443))], [(socket.AF_INET, socket.SOCK_STREAM, 6, '', ('192.168.5.3', 443))], [(socket.AF_INET, socket.SOCK_STREAM, 6, '', ('224.0.0.1', 443))], + [(socket.AF_INET, socket.SOCK_STREAM, 6, '', ('100.64.0.1', 443))], + [(socket.AF_INET, socket.SOCK_STREAM, 6, '', ('100.100.100.100', 443))], [(socket.AF_INET6, socket.SOCK_STREAM, 6, '', ('::1', 443, 0, 0))], [(socket.AF_INET6, socket.SOCK_STREAM, 6, '', ('fe80::1', 443, 0, 0))], [(socket.AF_INET6, socket.SOCK_STREAM, 6, '', ('ff00::1', 443, 0, 0))], [(socket.AF_INET6, socket.SOCK_STREAM, 6, '', ('fc00::1', 443, 0, 0))], + [(socket.AF_INET6, socket.SOCK_STREAM, 6, '', ('::ffff:100.64.0.1', 443, 0, 0))], ]