Overview
SSRF vulnerabilities in Node.js and Express can allow an attacker-controlled URL parameter to trigger outbound requests from your server. This can expose internal services, cloud metadata endpoints, or access restricted resources, potentially leaking credentials or enabling internal reconnaissance. In real-world deployments, SSRF can be leveraged to pivot within a network, cause denial of service by exhausting outbound bandwidth, or bypass access controls that rely on the server-side identity. No specific CVEs were provided for this guide; the focus here is on broadly understood SSRF patterns in Express-based apps and how to remediate them.
Code Fix Example
Node.js (Express) API Security Remediation
/* Vulnerable pattern */
const express = require('express');
const axios = require('axios');
const app = express();
app.get('/proxy', async (req, res) => {
const url = req.query.url; // user-controlled input
try {
const r = await axios.get(url, { timeout: 5000 });
res.set('Content-Type', r.headers['content-type'] || 'text/plain');
res.status(200).send(r.data);
} catch (e) {
res.status(500).send('Error fetching URL');
}
});
/* Fixed pattern */
const ALLOWED_HOSTS = ['example.com', 'api.example.org'];
function isAllowedUrl(input) {
try {
const u = new URL(input);
if (!['http:', 'https:'].includes(u.protocol)) return false;
return ALLOWED_HOSTS.includes(u.hostname);
} catch (e) {
return false;
}
}
app.get('/proxy-safe', async (req, res) => {
const url = req.query.url;
if (!isAllowedUrl(url)) return res.status(400).send('URL not allowed');
try {
const r = await axios.get(url, { timeout: 5000 });
res.set('Content-Type', r.headers['content-type'] || 'text/plain');
res.status(200).send(r.data);
} catch (e) {
res.status(500).send('Error fetching URL');
}
});
app.listen(3000, () => console.log('Server listening on 3000'));