Server-side request forgery (SSRF) is a weakness where an app fetches a URL or address that a user controls, without limiting where that request can go. The server then reaches places the user could never reach directly, such as internal admin tools or cloud metadata services. OWASP lists it as A10 in its 2021 Top 10, and CWE tracks it as CWE-918.
Updated October 2026
Why it matters
Your servers sit inside your network with trust that outside users do not have. They can often reach databases, internal dashboards and credential services. SSRF turns that trust against you. The result can be leaked cloud credentials, exposed internal data, or access to services that were never meant to face the internet. From there, customer data is often a short step away.
SSRF risk often grows with features. Webhooks, file imports, link previews, PDF rendering and single sign-on metadata all fetch remote content. Each new integration adds another place where the server makes a request on a user's behalf. Without a shared, well-tested fetch helper, every team writes its own checks, and some will miss a case such as an internal hostname or an IPv6 address.
A simple illustration
Acme Corp lets admins and members add a webhook URL or import an avatar from a link. The server fetches whatever URL is given. Nothing stops that URL from pointing at an internal address.
Vulnerable check:
def import_avatar(url):
resp = requests.get(url, timeout=5)
return save_image(resp.content)
Corrected check:
ALLOWED_SCHEMES = {"https"}
def import_avatar(url):
parsed = urlparse(url)
if parsed.scheme not in ALLOWED_SCHEMES:
raise BadRequest()
ip = resolve_once(parsed.hostname)
if not is_public_ip(ip):
raise BadRequest()
resp = fetch_pinned(ip, parsed, timeout=5, allow_redirects=False)
return save_image(resp.content, max_bytes=2_000_000)
The fix limits the scheme, resolves the host once, rejects private and reserved addresses, connects only to that resolved address, and disables redirects so the destination cannot change midway.
Why automated scanners often miss it
Many SSRF bugs are blind: the server makes the request but never shows the response to the user. A scanner that only reads responses sees nothing. Detection often needs an outside listener to see the callback, plus knowledge of which features fetch URLs (webhooks, imports, PDF renderers, link previews). Those features are often behind a login or a specific role, so an unauthenticated crawl never reaches them.
How to prevent it
- Avoid fetching user-supplied URLs where you can. Offer uploads instead.
- Use an allowlist of destinations when the set is known.
- Resolve DNS once, check the address, and connect to that exact address.
- Block private, loopback, link-local and metadata ranges, for IPv4 and IPv6.
- Disable redirects or re-check each hop.
- Route outbound fetches through an egress proxy with its own rules.
- Require tokens on cloud metadata services where your provider supports it.
How to test your own app for it
Only test software you own or have written permission to test.
- List every feature that makes a server-side request based on user input.
- Confirm each one validates scheme and destination on the server.
- Confirm private and metadata address ranges are blocked, including after redirects.
- Confirm outbound traffic from app servers goes through a controlled egress path.
- Review code for HTTP client calls that take a URL from a request.
How Wakefield helps
Wakefield's whitebox agents read your source on the default branch and on every pull request, trace risky paths, comment inline and offer a patch with a confidence level. A separate verifier replays each finding before it reaches you. See Whitebox testing.