Defending Against SSRF in Node.js Microservices
Server-Side Request Forgery is deadly. If your app fetches URLs provided by users, you are at risk. Here's how to lock down node-fetch and axios.
The SSRF Threat
If your application takes a URL from a user and fetches it (e.g., link unfurling, importing profile pictures, or webhook processing), you are vulnerable to Server-Side Request Forgery (SSRF).
An attacker can provide a URL like http://169.254.169.254/latest/meta-data/ (AWS metadata service) or http://localhost:6379 (internal Redis) and force your server to make requests to internal resources that should be hidden behind your firewall.
The Naive Defense
Many developers try to block localhost or internal IPs using regex.
if (url.includes('localhost') || url.includes('127.0.0.1')) {
throw new Error("Blocked");
}
This is bypassable. An attacker can use:
http://2130706433(Integer representation of 127.0.0.1)http://[::](IPv6 localhost)http://localtest.me(Public DNS that resolves to 127.0.0.1)
The Robust Defense
To prevent SSRF in Node.js, you must resolve the DNS record yourself and verify the IP address before establishing the TCP connection.
Using the ssrf-req-filter library or a custom http.Agent:
import http from 'http';
import { isIP } from 'net';
import ipaddr from 'ipaddr.js';
function isPrivateIP(ip: string) {
const addr = ipaddr.parse(ip);
return addr.range() !== 'unicast'; // Simplification
}
// You must bind this logic to the DNS lookup phase of your HTTP client.
// If the resolved IP is private, abort the request immediately.
Even better: deploy a proxy like Smokescreen (by Stripe) and force all outbound user-generated requests through it. It handles DNS rebinding, internal IP blocking, and protocol restrictions natively.
Tags
Related Blogs
Beyond JWTs: Designing a Stateful, High-Performance Session Architecture
Stateless JWTs are great until you need to instantly revoke a compromised session. Here's how to build a stateful, Redis-backed authentication system that handles 50k+ concurrent users with sub-millisecond validation.
Secure File Uploads: Why Trusting the Extension is Dangerous
Validating file uploads by checking if the filename ends in '.jpg' is a massive security hole. Learn how to securely process user uploads in Node.js.
The API security defaults I wish every tutorial taught
Rate limits, idempotency keys, request signing, structured error envelopes, and input validation. Not advanced security — table stakes. Here's how to implement them in a day.