TidyURLs
Go to Tools
BLOG
The TidyURLsJournal

Practical guides, tutorials, and insights about URLs, SEO, web development, and online marketing. Learn, troubleshoot, and get the most of the web.

Back to the Journal
TidyURLs Journal

SSRF Vulnerability Explained: The Risks of Fetching User-Supplied URLs

Practical insights, clear explanations, and useful ideas for understanding the web.

October 25, 20269 min read5 topics
SSRF Vulnerability Explained: The Risks of Fetching User-Supplied URLs
Explore the details
#SSRF#Web Security#Backend Development#URL Validation#Cloud Security
October 25, 20269 min read

A feature that fetches a URL entered by a user can quietly turn your server into a network client on that user’s behalf. If the server can reach destinations the user cannot—such as internal services or cloud metadata endpoints—the feature may expose sensitive data or allow unintended requests. This class of flaw is called server-side request forgery, or SSRF.

This guide explains how SSRF happens, why URL checks alone are not enough, and how backend teams can design URL-fetching features with layered controls. Examples use a fictional lab application and are for systems you own or are authorized to test.

Key takeaways

  • SSRF occurs when an application makes a server-side request based on attacker-controlled input without adequately controlling the destination.
  • A valid-looking URL or a public-looking hostname does not prove that the final network destination is safe.
  • Strongest designs use a narrow hostname allowlist, validate every resolved address, control redirects, and restrict outbound network access.
  • DNS rebinding and redirects can undermine checks that happen only once.
  • A URL parser can help inspect syntax, but it cannot enforce network-level SSRF protections.

How an SSRF vulnerability works

Consider a fictional service called LinkPreview. It accepts a URL and returns a page title and thumbnail so users can preview links. To do that, LinkPreview makes an HTTP request from its own server.

The risk appears when the application treats the submitted URL as trustworthy. A user might provide a URL that points to an internal administrative service, a private network address, or a cloud metadata service. If the server can reach that destination and returns the response to the user—or acts on a state-changing request—the user may gain access or cause actions they could not perform directly.

SSRF does not require the application to display the fetched response. A blind SSRF can still matter if a request reaches a sensitive service or triggers an internal action, even when the application only reports success or failure.

Why the server’s network position matters

A browser usually makes requests from the user’s device. An SSRF-prone backend makes requests from the server’s network environment, which may have access to internal services, privileged routes, or cloud infrastructure. The security boundary is therefore not just the URL string: it includes DNS resolution, the HTTP client, redirects, proxies, and network egress rules.

Common SSRF targets and failure modes

Private and special-purpose IP addresses

Internal services may use private IPv4 ranges, IPv6 local addresses, or other special-purpose addresses. A filter that blocks only one familiar address or one IPv4 range can miss other representations and address families. URL parsing and IP classification must account for both IPv4 and IPv6, as well as formats and address categories supported by the application’s network stack.

Blocking private addresses is useful, but it is not a complete policy by itself. A public address can host an unsafe service, and routing or proxy configuration can affect where a request actually goes. Where possible, allow only the specific destinations the feature needs.

Cloud metadata services

Cloud platforms may expose instance or workload metadata through a network endpoint. If an SSRF flaw can reach such an endpoint, the consequences may include disclosure of environment or identity information and, depending on the platform and configuration, credentials or other sensitive data. Cloud providers offer protections and configuration options, but they do not replace application-level destination controls and network isolation.

DNS rebinding and time-of-check/time-of-use gaps

A hostname can resolve to one address when the application checks it and a different address when the HTTP client connects. This is a DNS rebinding or resolution-time gap: the initial check and actual connection do not necessarily use the same destination.

A safer design resolves the hostname, validates all returned addresses against policy, and ensures the connection uses a validated address. The HTTP client must still use the original hostname for TLS certificate verification and the HTTP Host header; simply substituting an IP into a URL can break those checks. This behavior is client-library-specific and needs careful implementation and testing.

Redirects

A URL that initially points to an allowed public host may respond with a redirect to a disallowed destination. If the HTTP client follows redirects automatically, a check performed only on the original URL can be bypassed.

Either disable redirects or follow them manually with a strict redirect limit. Before each new request, validate the new scheme and hostname, resolve and check its addresses, and enforce the same policy as for the original URL.

Designing a safer URL-fetching feature

1. Decide whether arbitrary URLs are necessary

The safest design is often to avoid arbitrary server-side fetching. If the feature only needs previews from known services, accept a provider identifier or a URL from a tightly controlled set of hosts. A narrow allowlist is easier to reason about than trying to enumerate every unsafe destination.

2. Parse and normalize, then apply policy

Use a maintained URL parser to inspect the scheme, hostname, port, and credentials. Accept only the schemes the feature needs—typically HTTPS—and reject embedded username or password fields unless there is a specific, reviewed requirement. Normalize hostnames consistently before comparison, and compare complete hostnames rather than using a loose substring check.

A parser can help you inspect URL components, but parsing does not tell you whether a destination is safe to contact. It is not an SSRF defense on its own.

3. Validate DNS results and the connection destination

For a hostname-based policy, resolve the hostname and inspect every returned IPv4 and IPv6 address. Reject the request if any address violates the policy. Prevent a DNS change between validation and connection from redirecting the client to an unapproved address; use an HTTP client or controlled transport that can connect to a vetted address while preserving hostname-based TLS verification.

Do not assume that a check in application code is sufficient if the HTTP library performs its own resolution, uses a proxy, or follows redirects. Verify the behavior of the exact client and configuration you deploy.

4. Control redirects and request behavior

Disable automatic redirects unless the feature requires them. If redirects are needed, validate each hop and cap the number of redirects. Also constrain methods, request headers, response size, and timeouts. For a preview service, a small response limit and a short timeout can reduce resource abuse, though they do not replace destination validation.

5. Add network-level restrictions

Run fetchers in a restricted network environment. Egress firewalls, proxy rules, and service segmentation can block access to internal networks and sensitive endpoints even if an application check fails. Treat these controls as an additional layer: a proxy or firewall rule must match the actual routing architecture, including IPv6 and any permitted exceptions.

6. Protect cloud workloads

Follow the cloud provider’s guidance for restricting metadata access and assigning the minimum permissions needed to the workload. Where supported, use metadata-service protections and narrowly scoped workload identities. Do not rely on metadata protections alone to make arbitrary URL fetching safe.

A fictional lab workflow for reviewing LinkPreview

Use an isolated development environment with mock services and addresses reserved for documentation; do not test against systems you do not own or have explicit authorization to assess.

  1. Map the request path. Identify where user input enters, which component makes the outbound request, whether a proxy is used, and whether response data is returned or acted upon.
  2. Write the destination policy. For example, decide whether LinkPreview needs only a small set of known preview providers. Document allowed schemes, hosts, ports, address ranges, and redirect behavior.
  3. Test parsing and hostname rules. In unit tests, include malformed URLs, unexpected schemes, credentials in the authority section, lookalike hostnames, and IPv6 notation. Confirm that matching uses the parsed hostname and a deliberate normalization policy.
  4. Test resolution and redirects with mocks. Make a controlled test resolver return both allowed and prohibited addresses, and make a mock server redirect to a disallowed host. Confirm that the fetch is rejected before connecting to an unapproved destination and that redirects are revalidated.
  5. Verify network controls. In the lab, check that the fetcher cannot reach services outside its approved egress policy. Review proxy settings and IPv6 routing as well as IPv4.
  6. Log decisions safely. Record the policy outcome and relevant destination metadata for investigation, but avoid logging sensitive response bodies, credentials, or secrets.

These tests help verify the design, but passing a unit test suite does not prove that production routing, DNS, proxies, or cloud configuration behave the same way. Include integration tests and infrastructure review.

Common mistakes

  • Blocking only localhost. Internal destinations include more than one hostname and address family.
  • Checking the URL string instead of the parsed hostname. Substring checks can accept deceptive hostnames that merely contain an allowed name.
  • Validating DNS once and connecting later by hostname. The connection may resolve the name again and reach a different address.
  • Validating only the first redirect. Every redirect target needs the same checks, or redirects should be disabled.
  • Assuming a URL parser prevents SSRF. A parser identifies URL components; it does not control DNS, routing, redirects, or the eventual socket destination.
  • Treating a private-IP blocklist as the whole solution. It may miss address forms or network paths, and it does not limit requests to safe public services.
  • Relying on application checks alone. Egress controls and workload isolation provide important independent safeguards.

Defensive recommendations

For a production URL-fetching feature, prefer a strict allowlist and a purpose-built fetch service with limited network access. Validate the parsed URL, resolve and vet addresses, prevent resolution-to-connection gaps, and reapply policy to every redirect. Set resource limits and use minimal cloud permissions. Test the actual HTTP client, proxy, DNS, and network configuration rather than assuming their behavior.

If arbitrary destinations are not essential, redesign the feature so users choose from supported providers or submit content through a safer workflow. Reducing the set of destinations is generally easier to defend than trying to make every possible URL safe.

Conclusion

An SSRF vulnerability lets user-controlled input influence requests made from a server’s network position. The risk depends on what that server can reach and what the application does with the response. Safe URL fetching requires coordinated controls across parsing, DNS, connections, redirects, cloud permissions, and outbound networking. A URL parser is useful for inspection, but security comes from enforcing destination policy at the point of connection and backing it with restricted egress.

References