Apps Artificial Intelligence Cloud Computing CSS Cybersecurity Data Science Database Go JavaScript Linux Python Rust Software Engineering Web Development

Preventing SSRF in Backend Services That Fetch User-Supplied URLs

4 min read .
Preventing SSRF in Backend Services That Fetch User-Supplied URLs

Features that fetch a URL supplied by a user appear in webhook testers, image importers, link previewers, document converters, and integration platforms. They also create a server-side request forgery (SSRF) boundary: an attacker can try to make the backend send requests to destinations the attacker cannot reach directly.

A secure design needs more than a blacklist of suspicious strings.

Understand the trust boundary

The dangerous capability is not URL parsing itself. It is allowing untrusted input to influence a network connection made with the server’s network identity.

That server may be able to reach:

  • loopback services;
  • private network ranges;
  • cloud instance metadata endpoints;
  • internal control planes;
  • services protected only by network location.

The safest design is to avoid arbitrary outbound fetching when the product does not require it.

Prefer an allowlist of destinations

If the feature only needs to contact known providers, allow exact hosts or controlled domains instead of accepting the public internet.

For example, an integration that only calls an organization’s webhook gateway should accept destinations derived from configured provider identifiers rather than arbitrary URLs.

An allowlist dramatically simplifies validation because the application can compare a normalized hostname against an expected set.

Parse URLs with a real URL library

Do not validate URLs with substring tests such as:

reject if value contains "127.0.0.1"

URLs have user-info fields, percent encoding, IPv6 syntax, alternative textual forms, ports, and redirect behavior. Use the language’s URL parser and make policy decisions on parsed components.

At minimum, define which schemes are accepted. A web fetcher often needs only https and perhaps http. Reject local file schemes and unknown protocol handlers unless the feature explicitly requires them.

Validate the resolved destination, not only the hostname

Blocking hostnames such as localhost is insufficient. A public-looking hostname can resolve to a loopback, private, link-local, or otherwise sensitive address.

Before connection, resolve the hostname and reject addresses that policy forbids. Consider both IPv4 and IPv6.

The exact forbidden set depends on the environment, but commonly includes loopback, link-local, private address space, unspecified addresses, and infrastructure-specific metadata ranges.

DNS rebinding complicates validation

A dangerous pattern is:

  1. resolve the hostname for validation;
  2. decide it is public;
  3. let the HTTP client resolve the hostname again during connection.

An attacker controlling DNS may return a different address on the second resolution.

Robust implementations bind policy validation to the address actually used for the connection, often through a controlled resolver/dialer or an outbound proxy that enforces destination policy centrally.

Apply the policy to redirects

An allowed public URL can redirect to a private destination. Every redirect target must pass the same scheme, hostname, port, and resolved-address checks as the original URL.

Set a small redirect limit as well. Infinite or very long redirect chains waste resources even when every target is otherwise allowed.

Restrict ports when possible

If the feature only needs ordinary web content, there is little reason to permit arbitrary destination ports.

Allowing any port turns the fetcher into a limited internal port scanner and may expose protocols the application was never designed to parse safely. Restrict to the minimal required set.

Put network controls behind application validation

Application checks can have bugs. Defense in depth limits the result of a validation failure.

Useful infrastructure controls include:

  • running fetch workers in a network segment without access to control planes;
  • denying outbound access to private and metadata ranges at a firewall or proxy;
  • using an egress proxy that applies centralized destination rules;
  • avoiding ambient credentials on the fetching worker;
  • setting short connection, read, and total request timeouts.

The application should still validate URLs because network policy alone may be too coarse for product rules.

Limit response size and processing cost

SSRF protection should also consider resource exhaustion. A valid public URL can serve an enormous or endless response.

Set limits on:

  • maximum response bytes;
  • total request duration;
  • redirect count;
  • accepted content types when known;
  • decompression size;
  • concurrent outbound fetches.

Read only what the feature actually needs. A link previewer rarely needs to download a multi-gigabyte object.

Do not forward sensitive headers blindly

A backend fetcher should not copy inbound authorization headers, cookies, internal tracing credentials, or service tokens to an arbitrary destination.

Construct the outbound request from an explicit list of safe headers. If a provider requires credentials, associate them with a trusted provider configuration rather than with a user-selected hostname.

Log safely

Security investigation benefits from recording the normalized destination, decision outcome, and rejection reason. Do not log secrets embedded in URLs.

User-info components and query strings can contain tokens. Redact or omit them unless they are demonstrably safe to retain.

Common pitfalls

Blocking only RFC 1918 IPv4 ranges

Loopback, link-local, IPv6 local ranges, and environment-specific sensitive addresses remain reachable. Define policy using address classification rather than one short IPv4 list.

Validating before following redirects only

Every redirect is another untrusted destination decision.

Trusting a hostname because it ends with an allowed string

Naive suffix checks can accept lookalike domains. Compare canonical hostnames using boundary-aware domain logic, or use exact host allowlists where practical.

Relying on input validation without egress controls

SSRF is a network capability problem. Network isolation provides a second boundary when parser, resolver, or redirect logic is wrong.

Returning internal response bodies to the caller

Even when a connection is accidentally permitted, minimizing returned data can reduce impact. Do not expose raw upstream headers or bodies unless the feature requires them.

A safer architecture

For high-risk URL fetching, isolate the capability into a small worker or service with no access to sensitive internal networks and minimal credentials. Give it strict destination policy, bounded resources, and structured audit logs.

SSRF prevention is strongest when URL validation and network architecture agree on the same rule: user input may choose among intended public destinations, but it cannot turn the application into a general-purpose client for the server’s private network.

Related Posts

chevron-up