Overview
Affected Versions
CVE-2026-44578 affected Next.js built-in server from 13.4.13 to before 15.5.16 and also in 16.x up to before 16.2.5; fixed in 15.5.16 and 16.2.5. For Node.js/Express, this note applies to patterns that proxy via upgrade requests; ensure your server code is updated and follows the same mitigation principles.
Code Fix Example
// Vulnerable
const express = require('express');
const httpProxy = require('http-proxy');
const app = express();
const proxy = httpProxy.createProxyServer({ ws: true });
app.get('/proxy', (req, res) => {
const target = req.query.target;
if (!target) return res.status(400).send('target is required');
// Vulnerable: user-controllable target allows proxying to arbitrary destinations
proxy.web(req, res, { target }, err => res.status(502).send('Bad Gateway'));
});
app.listen(3000, () => console.log('Proxy listening on 3000'));
// Fixed
const allowedTargets = [ 'http://internal-service.local', 'https://api.example.com' ];
function isAllowedTarget (target) {
try {
const url = new URL(target);
if (!['http:', 'https:'].includes(url.protocol)) return false;
const host = url.hostname;
// Simple private IP guard: block common RFC1918 ranges
if (host === '127.0.0.1' || host.startsWith('10.') || host.startsWith('172.') || host.startsWith('192.168.'))
return false;
return allowedTargets.includes(url.origin);
} catch (e) {
return false;
}
}
app.get('/proxy', (req, res) => {
const target = req.query.target;
if (!target || !isAllowedTarget(target)) return res.status(400).send('target not allowed');
proxy.web(req, res, { target }, err => res.status(502).send('Bad Gateway'));
});