T09 · Insecure Skill Coding Practices
- Location
scripts/scrape_sitemap.py:53- Finding
DNS Rebinding Can Bypass Public-Only URL Validation
- Content
View full analysis
tuple[bool, str | None]: normalized = hostname.strip().strip(".").lower() if not normalized: return False, "empty hostname" if normalized in {"localhost"}: return False, "localhost is not allowed" if normalized.endswith((".local", ".localhost", ".internal", ".home.arpa")): return False, "internal-only hostname suffix is not allowed" try: ip = ipaddress.ip_address(normalized) except ValueError: pass else: if not ip.is_global: return False, f"non-public IP {ip} is not allowed" return True, None try: addrinfo = socket.getaddrinfo(normalized, None, proto=socket.IPPROTO_TCP) except socket.gaierror as exc: return False, f"hostname resolution failed: {exc}" resolved_ips: set[ipaddress.IPv4Address | ipaddress.IPv6Address] = set() for info in addrinfo: addr = info[4][0] try: resolved_ips.add(ipaddress.ip_address(addr)) except ValueError: continue if not resolved_ips: return False, "hostname did not resolve to usable IP addresses" for ip in resolved_ips: if not ip.is_global: return False, f"hostname resolves to non-public address {ip}" return True, None ``` The scraper subsequently opens the URL without pinning the previously validated IP address: ```python def fetch_text(url: str, timeout: float, user_agent: str) -> tuple[str | Non ...[truncated 5131 chars]- Remediation
View remediation
