/ blog/ssrf-defense-nodejs
blog / ssrf-defense-nodejs / overview.md

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

securitybackendnodejs
0
0