Overview
SSRF vulnerabilities in Node.js (Express) can allow an attacker to force your server to make requests to internal or external destinations, potentially exposing private services, cloud metadata, or sensitive data. In real-world scenarios, a vulnerable Express route that accepts a user-supplied URL and fetches it server-side effectively turns your application into a proxy, enabling blind or targeted network access, port scanning, or data exfiltration. If the server operates with broad network privileges or inside a permissive cloud VPC, the attacker may reach internal services, cloud metadata endpoints, or other sensitive resources from your environment. This class of flaws typically arises when input is unsafely consumed to initiate outbound requests without proper validation or isolation. No CVEs are provided in this guide, but the pattern aligns with common SSRF risks observed in Node.js/Express apps.
In Node.js with Express, SSRF commonly manifests when a route takes a URL from a client (query string or body) and uses server-side HTTP clients (like fetch, axios, or http/https modules) to retrieve that URL. The server’s outbound connections can then be leveraged to reach internal networks, cloud metadata services, or other systems that should be inaccessible from the public internet. Attackers may attempt to access private IP ranges, DNS-rebinding targets, or service endpoints that require no authentication, leading to information disclosure or lateral movement. Proper mitigation requires both input validation and network controls to prevent arbitrary server-side requests.
Remediation should combine application-level hardening with infrastructure controls. Implement strict allowlists of destinations, block private and non-routable IP addresses, and validate URLs using the WHATWG URL API. Enforce outbound egress restrictions at the host/container level and apply timeouts to prevent slow or stalled requests. Avoid design patterns that proxy user-controlled URLs unless absolutely necessary, and consider a dedicated, audited proxy that enforces strict policies. Logging, monitoring, and automated tests for SSRF paths help detect and respond to anomalous behavior.
Code Fix Example
Node.js (Express) API Security Remediation
/* Vulnerable pattern (SSR F risk) */
const express = require('express');
const fetch = require('node-fetch');
const app = express();
app.get('/proxy', async (req, res) => {
const url = req.query.url;
if (!url) return res.status(400).send('missing url');
const r = await fetch(url);
const body = await r.text();
res.send(body);
});
/* Safe version (mitigation): allowlist, URL parsing, IP checks */
const ALLOWED_HOSTS = ['example.com','api.example.com'];
function isPrivateIp(hostname) {
// In real code, resolve hostname and verify it's not in a private range using a library
return false;
}
app.get('/proxy', async (req, res) => {
const url = req.query.url;
if (!url) return res.status(400).send('missing url');
try {
const u = new URL(url);
if (!['http:','https:'].includes(u.protocol)) return res.status(400).send('invalid protocol');
if (!ALLOWED_HOSTS.includes(u.hostname)) return res.status(403).send('host not allowed');
if (isPrivateIp(u.hostname)) return res.status(403).send('private ip not allowed');
const r = await fetch(url, { timeout: 5000 });
const text = await r.text();
res.send(text);
} catch (e) {
res.status(400).send('invalid url');
}
});