flawopen.com/SSRF/Node.js fetch() SSRF
Does Node.js fetch() prevent server-side request forgery (SSRF)?
No. Server-side fetch() makes a network request from the server. If a caller chooses the destination, they may steer that request toward systems the server can reach but the caller cannot. It is like asking a trusted office courier to deliver a parcel without checking the address. The exposure depends on the server's network position, credentials, URL policy, and redirect behavior.
providerId) to a preconfigured origin. It avoids accepting an arbitrary URL.Root cause: the server trusts a caller-selected destination
Node.js fetch() is a general-purpose HTTP client, not an SSRF policy engine. It does not decide which networks your application should reach; browser CORS protections do not provide a server-side destination boundary. URL parsing alone is also insufficient: an allowed hostname can resolve to a prohibited address, and a response can redirect to another host. A vulnerable feature might fetch a user-supplied avatar, webhook, document, or preview URL.
How the request crosses the trust boundary
A caller influences a URL
An endpoint accepts a complete URL or enough host data to construct one, for example for an image preview.
The server sends the request
The server-side HTTP client uses the service network path, DNS, proxy configuration, and identity available to the process.
A redirect may change the destination
Fetch follows redirects by default. A destination that passed an initial check may return a Location pointing somewhere the application meant to forbid.
The response may expose reachable data
If policy and network controls permit access, internal services or cloud metadata may be reachable. The result depends on the environment and service configuration; it is not automatic for every fetch call.
Vulnerable and safer Node.js patterns
// Do not fetch an arbitrary caller-supplied URL.
const response = await fetch(userProvidedUrl);
// The caller selects a key, never a network destination.
const destinations = new Map([
["status", new URL("https://status.example/")],
["docs", new URL("https://docs.example/")],
]);
const target = destinations.get(providerId);
if (!target) throw new Error("Unknown provider");
const response = await fetch(target, {
redirect: "error",
signal: AbortSignal.timeout(3000),
});
if (!response.ok) throw new Error("Upstream request failed");
When users must submit URLs
Prefer a product design that accepts a provider ID and builds the request from a fixed destination map. If arbitrary public URLs are essential, allow only required schemes and ports; reject user-info, loopback, private, link-local, and other prohibited IPv4 and IPv6 destinations; resolve and validate every address; and ensure the client connects to a validated address without a second unchecked lookup. Disable automatic redirects or revalidate every hop. Enforce outbound network rules independently, including blocks for cloud metadata endpoints such as 169.254.169.254 and the enabled IPv6 metadata address. Bound connection time, response size, and concurrency; never forward internal credentials to the fetched host.
SSRF prevention checklist
- ✓Replace arbitrary URL input with a fixed mapping from a validated provider key to an application-owned destination wherever possible.
- ✓Require
https:and expected ports; reject credentials in the URL, unexpected hostnames, IP literals, and prohibited address ranges. - ✓Disable redirects with
redirect: "error"; if redirects are required, validate every target before connecting. - ✓Prevent DNS rebinding by validating all A/AAAA answers and binding the connection to a validated address while preserving hostname verification. Apply the rule to retries and proxies too.
- ✓Apply egress firewall or proxy policy to block loopback, private, link-local, and metadata networks, including IPv6. Do not rely on application checks alone.
- ✓Set timeouts, response-byte and concurrency limits, and avoid forwarding cookies, authorization headers, or cloud credentials to fetched destinations.
- ✓On AWS, require IMDSv2 and restrict metadata access as defense in depth; this does not replace URL validation and network egress controls.
Frequently asked questions
No. Redirects, IPv4 and IPv6 representations, DNS rebinding, proxies, and resolution/connection races can defeat a simple check. Prefer a fixed destination allowlist. When arbitrary destinations are required, validate every resolved address and make the connection use that validated result; enforce the same policy at network egress.
No. IMDSv2 requires a token flow and can reduce exposure to some SSRF paths, but SSRF can target other internal services or metadata endpoints under different configurations. Keep destination and egress controls in place.
Primary sources
- OWASP — Server-Side Request Forgery Prevention Cheat Sheet
- Node.js — Global fetch API
- WHATWG Fetch Standard — Redirect mode
- AWS — Configure EC2 Instance Metadata Service options
- CWE-918 — Server-Side Request Forgery