In this lesson, you will learn how to prevent Server-Side Request Forgery (SSRF) by implementing strict validation patterns when your application makes outgoing requests to internal network resources.
The SSRF Vulnerability
SSRF occurs when an attacker forces your server to make unauthorized requests to internal systems that are not exposed to the public internet. If your application accepts a URL as input—for example, to fetch a user's profile image or crawl a webpage—and then uses that input to perform a fetch or axios request, an attacker might provide a URL like http://localhost:8080/admin or http://169.254.169.254/latest/meta-data/ to probe your infrastructure or steal cloud metadata credentials.
Sanitizing Internal Calls
To defend against this, you must treat user-supplied URLs as untrusted data. Relying on simple string matching is insufficient, as attackers can use IP obfuscation or DNS rebinding. Instead, implement a strict "allow-list" approach using a URL parsing strategy.
Here is how you can sanitize outgoing requests:
const { URL } = require('url');
function isSafeUrl(userInput) {
try {
const parsed = new URL(userInput);
// 1. Strict protocol enforcement
if (parsed.protocol !== 'https:') return false;
// 2. Resolve hostname and block internal/private ranges
// Use an IP-range filtering library or internal validation
const blockedRanges = ['127.0.0.1', '169.254.169.254', '192.168.0.0/16'];
if (isPrivateIp(parsed.hostname)) return false;
return true;
} catch (e) {
return false;
}
}
Defense-in-Depth
Beyond input validation, you should minimize the blast radius of your Node.js processes. Configure your network firewall to explicitly deny outgoing requests from your application server to sensitive internal metadata services or management endpoints. Even if your code is tricked into making a request, the network layer acts as a final fail-safe, preventing the request from ever reaching internal targets. Never allow your server to follow redirects automatically when processing user-provided URLs, as these can be used to bypass initial input filters.
Key Takeaway: Always validate and constrain the destination of any outgoing request initiated by user input using a strict allow-list and network-level egress filtering.