Notes · · 2 min read
Scanning a URL without becoming an SSRF proxy
Nocturn Quality runs ordinary page requests against public sites. That sentence hides the hard part: the service must fetch a URL chosen by a stranger without letting that stranger choose the address it actually connects to.
Server-side request forgery is usually described as a missing validation. In practice it is a gap between two moments: the moment you check a URL and the moment your HTTP client connects to it. Anything that can change in between — DNS, redirects, the client's own resolution — is part of the attack surface.
The URL is not the destination
The first mistake is to validate the string and then hand it to a generic HTTP client. Between the check and the connection, DNS can resolve differently. The scanner resolves the host itself, rejects private and reserved ranges, and connects only to the address it verified.
That closes the obvious cases — localhost, private ranges, link-local addresses — but it also changes the client. The verified address, not the hostname, is what the request is allowed to use.
Every redirect is a new decision
A public URL can redirect to a private one. Treating a redirect as a detail of the original request is how a scanner ends up fetching a metadata endpoint. The scanner re-checks every redirect hop with the same rules as the first request.
The useful mental model is simple: a redirect is not a continuation, it is a second request with a new destination. If the second destination would have been refused on its own, it is refused here too.
Keep the surface small
The scanner allows ports 80 and 443 only and caps response bodies. Timeouts and body limits are not performance tuning in this context; they are part of the security boundary. Every extra protocol, port or unlimited read is another way to make the service do something it was not designed to do.
Passive by default, invasive only with proof
Anyone can run the same page requests a browser or crawler makes. Load tests and source audits run only against targets the customer has proved they control. This keeps the public tool useful without turning it into a traffic source that can be aimed at someone else.
The distinction is not cosmetic. A passive scan observes what is already publicly served. A load test creates traffic, and a source audit needs access. Both require a different level of authorisation from a URL in a text box.
What this does not solve
SSRF defences are a series of windows, not a single wall. DNS and routing can change, unusual network setups and IPv6 need their own checks, and a scanner can still be used to make a lot of legitimate requests. The point is not to make the feature risk-free. The point is to make the risky path explicit, small and tested.
The checks themselves are ordinary: resolve, verify, connect, repeat. The discipline is doing them in that order, every time, including on the hop nobody expected.
Built while working on
Nocturn Quality — read the case study