Security: harden is_public_ip

This commit is contained in:
shamoon
2026-08-27 00:21:03 -07:00
parent f6f37898e8
commit a298568962
2 changed files with 52 additions and 0 deletions
+12
View File
@@ -6,6 +6,17 @@ from urllib.parse import urlparse
import httpx
# Ranges ipaddress does not report as private, but which routinely front
# internal infrastructure.
_NON_PUBLIC_NETWORKS = (
# RFC 6598 shared address space: ISP CGNAT, and the default pod/service
# CIDR on several managed Kubernetes offerings.
ipaddress.ip_network("100.64.0.0/10"),
# RFC 6052 NAT64 well-known prefix: 64:ff9b::7f00:1 is 127.0.0.1 wherever
# a NAT64 gateway exists.
ipaddress.ip_network("64:ff9b::/96"),
)
def is_public_ip(ip: str | int) -> bool:
try:
@@ -16,6 +27,7 @@ def is_public_ip(ip: str | int) -> bool:
or obj.is_link_local
or obj.is_multicast
or obj.is_unspecified
or any(obj in network for network in _NON_PUBLIC_NETWORKS)
)
except ValueError: # pragma: no cover
return False
+40
View File
@@ -4,6 +4,7 @@ import httpx
import pytest
from paperless.network import PinnedHostHTTPTransport
from paperless.network import is_public_ip
def test_pinned_host_transport_blocks_internal_rebinding():
@@ -48,3 +49,42 @@ def test_pinned_host_transport_rewrites_to_vetted_ip():
response = transport.handle_request(request)
assert response.status_code == 200
@pytest.mark.parametrize(
"address",
[
"127.0.0.1",
"10.0.0.5",
"169.254.169.254",
"::1",
"fc00::1",
"fe80::1",
# RFC 6598 shared address space, incl. both edges of the /10
"100.64.0.0",
"100.64.0.1",
"100.127.255.255",
# RFC 6052 NAT64 well-known prefix, embedding 127.0.0.1 and 10.0.0.5
"64:ff9b::7f00:1",
"64:ff9b::a00:5",
],
)
def test_is_public_ip_blocks_non_public_addresses(address):
assert not is_public_ip(address)
@pytest.mark.parametrize(
"address",
[
"8.8.8.8",
"142.250.185.196",
"2606:4700:4700::1111",
# just outside the ranges above, must stay reachable
"100.63.255.255",
"100.128.0.0",
"64:ff9a::1",
"64:ff9c::1",
],
)
def test_is_public_ip_allows_public_addresses(address):
assert is_public_ip(address)