SSRF

SSRF in Node.js Express: Axios pollution fix [Month Year] [CVE-2026-40175]

[Fixed 2026-04] Updated CVE-2026-40175

Overview

The real-world impact of this class of vulnerability is that untrusted input can poison object prototypes via a vulnerable Axios configuration path, enabling attackers to escalate from a prototype pollution gadget to remote code execution or cloud-wide compromise (including bypassing IMDSv2 in AWS) in Node.js apps using Express. CVE-2026-40175 documents a prototype-pollution chain in Axios prior to 1.15.0, where polluted prototypes can influence application logic or dependent gadgets, creating a foothold for powerful attacks. The CVE references CWE-113, CWE-444, and CWE-918 to illustrate how improper input handling, prototype pollution, and SSRF-like behavior can lead to severe outcomes if not mitigated. This guide focuses on how such issues manifest in a Node.js (Express) server and how to remediate them in practice. In exploiting this issue, an attacker provides crafted input that is merged into Axios request configuration. If user-controlled data is directly merged (for example via Object.assign or deep-merge utilities) into the Axios config, an __proto__ payload can pollute the global Object prototype and downstream code paths that rely on the polluted properties. In complex gadget chains, polluted prototypes can cause unexpected behavior, including making the server issue unauthorized requests (SSRF-like behavior) or enabling code execution in a compromised environment. The fixed version (Axios 1.15.0) removes or mitigates the risky merge behavior, reducing the risk of prototype pollution and its capability to cascade into RCE or cloud-compromise scenarios. To minimize risk in Node.js (Express) applications, adopt explicit input validation and a strict, whitelist-based approach to request configuration. Do not merge arbitrary user data into Axios configuration, upgrade dependencies to patched versions, and audit your dependency graph for gadget chains that could be triggered by polluted prototypes. Implement server-side SSRF protections, minimize trust in client input, and consider alternative patterns such as constructing Axios requests from explicit, server-controlled fields rather than user-supplied objects.

Affected Versions

Axios < 1.15.0

Code Fix Example

Node.js (Express) API Security Remediation
// Vulnerable pattern (allows prototype pollution via user-controlled config)
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());

app.post('/fetch', async (req, res) => {
  // User can influence entire Axios config via req.body.config
  const userConfig = req.body.config || {};
  const axiosConfig = Object.assign({ url: req.body.url, method: 'GET' }, userConfig);
  try {
    const response = await axios(axiosConfig);
    res.status(200).send(response.data);
  } catch (err) {
    res.status(500).send('Error');
  }
});

app.listen(3000, () => console.log('Server started'));

// Fixed pattern (avoid merging untrusted input; use explicit, server-controlled config)
app.post('/fetch-secure', async (req, res) => {
  // Explicitly construct a sanitized config from whitelisted fields only
  const url = req.body.url;
  const method = (req.body.method && ['GET','POST','PUT','PATCH','DELETE'].includes(req.body.method.toUpperCase())) ? req.body.method.toUpperCase() : 'GET';
  const headers = (req.body.headers && typeof req.body.headers === 'object') ? req.body.headers : {};
  const data = (req.body.data && typeof req.body.data === 'object') ? req.body.data : undefined;
  const timeout = (typeof req.body.timeout === 'number' && req.body.timeout > 0) ? req.body.timeout : undefined;

  const axiosConfig = { url, method, headers };
  if (data !== undefined) axiosConfig.data = data;
  if (timeout !== undefined) axiosConfig.timeout = timeout;

  try {
    const response = await axios(axiosConfig);
    res.status(200).send(response.data);
  } catch (err) {
    res.status(500).send('Error');
  }
});

// Note: Ensure Axios is upgraded to 1.15.0+ in package.json

CVE References

Choose which optional cookies to allow. You can change this any time.