Why a "Check This URL" Tool Needs SSRF Protection
Any server-side feature that fetches a URL you supply can be tricked into reaching internal addresses instead — what that attack looks like and how it's actually stopped.
· 3 min read
A tool that fetches a URL you supply — to check its headers, follow its redirects, or crawl its links — is one of the most common places a real security bug shows up in otherwise ordinary software. That bug has a name: Server-Side Request Forgery (SSRF), and its shape is always the same. A server with no restriction on its outbound requests will connect to http://169.254.169.254/ or http://localhost:6379 just as willingly as it connects to https://example.com, because from its point of view they're all just URLs.
Why that one address matters
169.254.169.254 is the link-local address cloud providers (AWS, GCP, Azure) use for their own instance metadata service — the endpoint a VM queries to fetch its own temporary credentials. If a public "paste a URL, I'll fetch it" feature can be pointed at that address, an attacker can read credentials meant only for the server itself. It's the single most common real-world SSRF target, and it's simultaneously just a private-network address like 127.0.0.1 or 10.0.0.5 — the vulnerability isn't specific to that IP, it's that any internal address is reachable at all.
Why the naive fix doesn't work
Checking whether a URL's hostname "looks internal" (blocking localhost, say) is not the same as checking where it actually resolves. A hostname is just a string until DNS resolves it — and DNS can be configured to answer with a private address for a name that looks completely ordinary. A real fix has to resolve the hostname before connecting and inspect the actual IP address, not pattern-match on the URL's text.
There's a second layer that has to be done right: redirects. A URL can pass every check on its own and then respond with a 30x that points somewhere else entirely — a public entry point that immediately redirects to http://localhost/admin. A safe fetch has to follow redirects manually (not delegate that to the HTTP client's automatic behavior) and re-validate every single hop against the same rules, not just the first one.
What a real defense looks like
Put together, a safe outbound fetch has to:
- Restrict the scheme to
http/https— nofile://, nogopher://. - Resolve the hostname and reject the request if any of the resolved addresses falls in a private, loopback, link-local, or reserved range (the full
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.0/8,169.254.0.0/16list, plus the IPv6 equivalents). - Re-run that same check at every redirect hop, since the target can change mid-request.
- Bound the timeout and response size, so even an allowed target can't be used to tie up the server indefinitely.
HTTP Header Checker, Redirect Chain Checker, and Broken Link Checker all fetch a visitor-supplied URL server-side (a browser's own CORS restrictions make doing this client-side for an arbitrary site impossible), so all three apply exactly this checklist before opening a connection. SSL Certificate Checker needs the same address validation but can never use an HTTP fetch at all — reading a TLS certificate means opening a raw socket directly, so the hostname is checked the same way before that socket is ever opened. DNS Lookup is the one tool in this group that's structurally exempt from all of this: it only asks a public DNS resolver what a name maps to and never connects to the address it gets back, so there's nothing for the target address itself to attack.

