From cc3dbbe804ba3cc683baa096a923b868b011e75c Mon Sep 17 00:00:00 2001 From: Xubin Ren <52506698+Re-bin@users.noreply.github.com> Date: Sun, 26 Jul 2026 22:25:32 +0800 Subject: [PATCH] fix(security): block IPv6 unspecified SSRF targets --- nanobot/security/network.py | 1 + tests/providers/test_image_generation_security.py | 9 +++++++-- tests/security/test_security_network.py | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/nanobot/security/network.py b/nanobot/security/network.py index 95523f3a..23daf980 100644 --- a/nanobot/security/network.py +++ b/nanobot/security/network.py @@ -20,6 +20,7 @@ _BLOCKED_NETWORKS = [ ipaddress.ip_network("169.254.0.0/16"), # link-local / cloud metadata ipaddress.ip_network("172.16.0.0/12"), ipaddress.ip_network("192.168.0.0/16"), + ipaddress.ip_network("::/128"), # unspecified; may route to local host ipaddress.ip_network("::1/128"), ipaddress.ip_network("fc00::/7"), # unique local ipaddress.ip_network("fe80::/10"), # link-local v6 diff --git a/tests/providers/test_image_generation_security.py b/tests/providers/test_image_generation_security.py index 466b74cd..44b586a7 100644 --- a/tests/providers/test_image_generation_security.py +++ b/tests/providers/test_image_generation_security.py @@ -28,8 +28,13 @@ def _resolve_public(host: str, port: int | None, *args, **kwargs): ] +@pytest.mark.parametrize( + "url", + ["http://127.0.0.1/admin", "http://[::]/admin"], + ids=["ipv4-loopback", "ipv6-unspecified"], +) @pytest.mark.asyncio -async def test_generated_image_download_blocks_private_target() -> None: +async def test_generated_image_download_blocks_unsafe_target(url: str) -> None: requested = False async def handler(request: httpx.Request) -> httpx.Response: @@ -39,7 +44,7 @@ async def test_generated_image_download_blocks_private_target() -> None: with pytest.raises(ImageGenerationError, match="blocked unsafe generated image URL"): await _download_image_data_url( - "http://127.0.0.1/admin", + url, transport=httpx.MockTransport(handler), ) diff --git a/tests/security/test_security_network.py b/tests/security/test_security_network.py index fc4ea767..9b71022f 100644 --- a/tests/security/test_security_network.py +++ b/tests/security/test_security_network.py @@ -148,6 +148,7 @@ def test_blocks_sampled_addresses_from_internal_networks(): "169.254.0.0/16", "172.16.0.0/12", "192.168.0.0/16", + "::/128", "::1/128", "fc00::/7", "fe80::/10",