mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-20 23:31:31 +02:00
A registry only holds the registered name, but the lookup asked for the
target verbatim, so every subdomain target 400'd at the registry:
scanme.nmap.org went to the .org RDAP server, which has no such object.
Any target below the apex — api.example.com, www.bbc.co.uk — therefore
carried a permanent "WHOIS failed" badge. Lookups now ask for the
registrable domain, so bbc.co.uk is reached through the public-suffix
table rather than the last two labels.
Private and reserved address space has no registry record at all. That
was reported as a failure carrying the RDAP library's own wording
("IPv4Address 192.168.0.0/24 is private"), which put an error in the
activity feed and a red badge on the target for a fact about the
address. It is now recognised before any query is made and recorded as
not applicable, with a sentence that says why. The target page already
worded this correctly for a single private address; it now recognises a
private range too.
One lookup key is shared by the cache, the stored record and the API
read-back, so a domain and its subdomains resolve to one registry record
instead of re-querying on every miss.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6LcH8uUddjJbKrahf34ys
37 lines
1.1 KiB
Python
37 lines
1.1 KiB
Python
import ipaddress
|
|
import socket
|
|
from urllib.parse import urlsplit
|
|
|
|
|
|
def is_registry_routable(value: str) -> bool:
|
|
"""Whether an address or netblock sits in public space an RIR can hold a record for."""
|
|
try:
|
|
net = ipaddress.ip_network(value.strip(), strict=False)
|
|
except ValueError:
|
|
return False
|
|
return net.is_global and not net.is_multicast
|
|
|
|
|
|
def validate_public_https_url(raw: str, *, label: str = "URL") -> None:
|
|
parts = urlsplit(raw)
|
|
if parts.scheme != "https" or not parts.hostname:
|
|
msg = f"{label} must be an https:// URL."
|
|
raise ValueError(msg)
|
|
try:
|
|
infos = socket.getaddrinfo(parts.hostname, None)
|
|
except OSError as exc:
|
|
msg = f"Cannot resolve {label} host: {exc}"
|
|
raise ValueError(msg) from exc
|
|
for info in infos:
|
|
ip = ipaddress.ip_address(info[4][0])
|
|
if (
|
|
ip.is_private
|
|
or ip.is_loopback
|
|
or ip.is_link_local
|
|
or ip.is_reserved
|
|
or ip.is_multicast
|
|
or ip.is_unspecified
|
|
):
|
|
msg = f"{label} resolves to a disallowed address."
|
|
raise ValueError(msg)
|