Security release: fixes an SSRF in the favicon fetcher (GHSA-543h-3j64-gm5q).
isPrivateIP previously checked only loopback and RFC 1918, so link-local
(including the 169.254.169.254 cloud metadata endpoint), CGNAT, multicast and
IPv6 transition addresses that embed a private IPv4 were all treated as public.
A public host could also 302 onto an internal address.
This release blocks the full set of ranges IANA marks as not globally reachable,
at two layers: a pre-flight host check and, crucially, a Dialer.Control
callback that runs on every connection attempt — the initial request, every
redirect hop, and every candidate IP when a host resolves to several. IPv6
transition formats (6to4, NAT64, Teredo) are decoded and their embedded IPv4
re-checked rather than blocked outright, so IPv6-only and 6to4 deployments keep
working.
Reported independently by tonghuaroot and Usman Baig (uz1mani).
Behaviour change for library users: outbound fetches no longer honour
HTTP_PROXY/HTTPS_PROXY. With a proxy configured the dialer connects to the
proxy, so the address filter would never see the real target.
Note: supplying your own client via WithHTTPClient bypasses this
protection entirely — apply your own dial-time filter if you do.