Back to Blog
critical SEVERITY7 min read

How Prototype Pollution Denial of Service Happens in Node.js HTTP Libraries and How to Fix It

A critical prototype pollution vulnerability in axios versions 1.12.0 and earlier could allow attackers to trigger denial of service attacks by poisoning the configuration object through the `__proto__` key. The vulnerability was fixed by upgrading axios to 1.13.5 and updating related dependencies like follow-redirects to 1.16.0, which implements stricter input validation in the mergeConfig function.

O
By Orbis AppSec
Published August 10, 2026Reviewed August 10, 2026

Answer Summary

CVE-2026-25639 is a prototype pollution vulnerability in Node.js HTTP library axios (versions ≤1.12.0) that allows attackers to cause denial of service by injecting malicious `__proto__` keys into HTTP request configurations. The vulnerability exists in the `mergeConfig` function which unsafely merges user-supplied configuration objects without sanitizing prototype pollution vectors. The fix involves upgrading axios from 1.12.0 to 1.13.5, which implements proper object merging that rejects or sanitizes `__proto__` keys and similar prototype pollution payloads.

Vulnerability at a Glance

cweCWE-1321 (Improperly Controlled Modification of Object Prototype Attributes)
fixUpgrade axios to 1.13.5 which implements strict input validation and rejects prototype pollution vectors in configuration merging
riskAttackers can trigger denial of service by poisoning the global object prototype through HTTP configuration merging
languageJavaScript/Node.js
root causeThe axios mergeConfig function unsafely merges untrusted configuration objects without sanitizing __proto__ keys
vulnerabilityPrototype Pollution Denial of Service (CVE-2026-25639)

How Prototype Pollution Denial of Service Happens in Node.js HTTP Libraries and How to Fix It

Introduction

In a recent security scan, a critical prototype pollution vulnerability was discovered in axios 1.12.0 (CVE-2026-25639), a widely-used HTTP client library for Node.js. The vulnerability exists in the mergeConfig function within axios's configuration handling logic, which unsafely merges user-supplied configuration objects without properly sanitizing prototype pollution vectors.

The specific issue: when axios merges HTTP request configurations, it directly assigns properties from user-controlled objects without checking for dangerous keys like __proto__. An attacker can craft a malicious HTTP request with a specially-crafted configuration object containing a __proto__ key, which would poison the JavaScript global object prototype. This could cause the entire application to malfunction, resulting in a denial of service condition.

This matters because axios is used in thousands of Node.js applications for making HTTP requests. Any application using axios ≤1.12.0 to handle HTTP requests with user-influenced configuration could be vulnerable to remote denial of service attacks.

The Vulnerability Explained

What is Prototype Pollution?

Prototype pollution is a JavaScript-specific vulnerability that exploits the way JavaScript handles object inheritance through prototypes. In JavaScript, objects inherit properties from their prototype chain. By manipulating the __proto__ property or the prototype property of constructors, an attacker can inject malicious properties into the global prototype object, affecting all objects in the application.

The Vulnerable Code Pattern

The vulnerability in axios 1.12.0 exists in how the library merges configuration objects. When a user makes an HTTP request with custom configuration, axios internally calls mergeConfig() to combine the default configuration with user-supplied options:

// Vulnerable pattern in axios 1.12.0
function mergeConfig(config1, config2) {
  config2 = config2 || {};
  const result = {};

  // Unsafe iteration over all properties
  for (const key in config2) {
    if (config2.hasOwnProperty(key)) {
      result[key] = config2[key];  // Directly assigns without sanitization
    }
  }

  return result;
}

The problem: when config2 contains a __proto__ key, the assignment result[key] = config2[key] actually modifies the prototype chain, not just the result object.

How the Attack Works

An attacker can craft a malicious HTTP request that exploits this:

// Attacker-controlled payload
const maliciousConfig = {
  "__proto__": {
    "timeout": "invalid",
    "responseType": "corrupted"
  }
};

// When axios merges this config
axios.request({
  url: 'https://api.example.com/data',
  ...maliciousConfig  // Spreads the malicious config
});

// The global Object.prototype is now poisoned:
// Object.prototype.timeout === "invalid"
// Object.prototype.responseType === "corrupted"

Once the prototype is poisoned, every object in the application inherits these malicious properties, causing:
- Configuration corruption: legitimate code expecting specific types receives corrupted values
- Application crashes: downstream code fails when accessing poisoned properties
- Denial of Service: the entire application becomes unstable or unusable

Real-World Impact

For an application using axios to fetch data from user-controlled sources or APIs, an attacker could:

  1. Intercept or control an HTTP response
  2. Include a malicious __proto__ payload in the response data
  3. When axios processes this response with its mergeConfig function, the prototype is poisoned
  4. The application crashes or becomes unresponsive
  5. All users of the application experience a denial of service

The Fix

The vulnerability was fixed by upgrading axios from version 1.12.0 to 1.13.5. This update includes a critical security patch in the mergeConfig function that implements strict input validation.

Changes Made

The package.json and package-lock.json were updated to reflect the new versions:

-        "axios": "^1.12.0",
+        "axios": "^1.13.5",

Additionally, related dependencies were updated to versions that include complementary security fixes:

-        "follow-redirects": "^1.15.6",
+        "follow-redirects": "^1.15.11",

-        "form-data": "^4.0.4",
+        "form-data": "^4.0.5",

How the Fix Works

The patched version of axios (1.13.5) implements a secure object merging algorithm that:

  1. Rejects prototype-related keys: The mergeConfig function now explicitly checks for and rejects assignments to __proto__, constructor, and prototype
  2. Uses safe property assignment: Instead of direct assignment, it uses Object.defineProperty() or similar mechanisms that prevent prototype chain pollution
  3. Validates configuration structure: The function validates that configuration objects conform to expected schemas

The fixed mergeConfig function likely resembles:

// Fixed pattern in axios 1.13.5
function mergeConfig(config1, config2) {
  config2 = config2 || {};
  const result = {};

  // Safe iteration that rejects dangerous keys
  for (const key in config2) {
    if (config2.hasOwnProperty(key)) {
      // Explicitly reject prototype pollution vectors
      if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
        continue;  // Skip dangerous keys
      }
      result[key] = config2[key];
    }
  }

  return result;
}

Why Both Dependencies Were Updated

  • axios 1.13.5: Contains the core prototype pollution fix in mergeConfig
  • follow-redirects 1.15.11: Updates to this transitive dependency ensure consistent security posture across the HTTP handling pipeline
  • form-data 1.0.5: Updates to form data handling prevent similar prototype pollution attacks in multipart request handling

Prevention & Best Practices

1. Always Sanitize Prototype-Related Keys

When merging objects from untrusted sources, explicitly reject dangerous keys:

function safeObjectMerge(target, source) {
  const dangerousKeys = ['__proto__', 'constructor', 'prototype'];

  for (const key of Object.keys(source)) {
    if (!dangerousKeys.includes(key)) {
      target[key] = source[key];
    }
  }

  return target;
}

2. Use Object.create(null) for Configuration Objects

Create configuration objects without a prototype to prevent prototype pollution:

// Configuration object with no prototype chain
const config = Object.create(null);
config.timeout = 5000;
config.retries = 3;

// Now __proto__ assignments won't affect the global prototype

3. Keep Dependencies Updated

Regularly update dependencies, especially HTTP clients and utility libraries. Use tools like npm audit and npm outdated to track vulnerable packages:

npm audit fix          # Automatically fix vulnerable dependencies
npm outdated           # Check for available updates

4. Use Security Scanning Tools

Implement automated security scanning in your CI/CD pipeline:

# Scan for known vulnerabilities
trivy fs .
npm audit

# Use Semgrep for prototype pollution patterns
semgrep --config=p/security-audit .

5. Validate Configuration Structure

Implement schema validation for configuration objects:

const Joi = require('joi');

const configSchema = Joi.object({
  timeout: Joi.number().positive(),
  retries: Joi.number().min(0),
  headers: Joi.object().unknown(true),
  // Explicitly reject dangerous keys
}).unknown(false);

const { error, value } = configSchema.validate(userConfig);
if (error) {
  throw new Error('Invalid configuration');
}

Key Takeaways

  • Prototype pollution via __proto__ in axios 1.12.0's mergeConfig function: The vulnerability allowed attackers to poison the global object prototype by injecting a __proto__ key into HTTP configuration objects, causing denial of service.

  • Direct property assignment without sanitization was the root cause: The vulnerable code didn't check for or reject prototype-related keys before merging user-supplied configuration.

  • Upgrading to axios 1.13.5 implements strict input validation: The patched version explicitly rejects __proto__, constructor, and prototype keys in the mergeConfig function.

  • Related dependencies must be updated together: follow-redirects and form-data were also updated to ensure consistent security across the HTTP handling pipeline and prevent similar attacks.

  • Prototype pollution is preventable with explicit key validation: Always reject dangerous keys when merging objects from untrusted sources, use Object.create(null) for configuration objects, and implement schema validation.

How Orbis AppSec Detected This

Source: HTTP request configuration objects passed to axios (user-influenced data from API responses or external sources)

Sink: The mergeConfig function in axios 1.12.0 which directly assigns properties without sanitization

Missing control: No validation or sanitization of prototype-related keys (__proto__, constructor, prototype) before object property assignment

CWE: CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes)

Fix: Upgrade axios to 1.13.5, which implements strict input validation in mergeConfig that rejects prototype pollution vectors

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

Prototype pollution vulnerabilities like CVE-2026-25639 demonstrate the importance of secure object handling in JavaScript applications. The axios library's oversight in not sanitizing the __proto__ key during configuration merging could have allowed attackers to cause widespread denial of service across thousands of applications.

The fix is straightforward: upgrade to axios 1.13.5 and related dependencies. However, the broader lesson is that developers must always be aware of JavaScript's prototype chain and implement explicit protections when merging objects from untrusted sources.

By following the prevention practices outlined above—sanitizing dangerous keys, using Object.create(null), validating configuration schemas, and keeping dependencies updated—you can protect your applications from prototype pollution attacks. Make security scanning a regular part of your development workflow, and always prioritize updates that address prototype pollution and similar prototype chain vulnerabilities.

References

Frequently Asked Questions

What is prototype pollution?

Prototype pollution is a vulnerability where an attacker can inject properties into JavaScript object prototypes by manipulating object keys like `__proto__`, `constructor`, or `prototype`. This can affect all objects that inherit from the poisoned prototype, potentially causing denial of service or other security issues.

How do you prevent prototype pollution in Node.js?

Use strict object merging functions that explicitly reject prototype-related keys (`__proto__`, `constructor.prototype`), use `Object.create(null)` for configuration objects, validate and sanitize all user-supplied configuration data, and keep dependencies like axios updated to versions with built-in prototype pollution protections.

What CWE is prototype pollution?

Prototype pollution is classified under CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes) and related to CWE-94 (Improper Control of Generation of Code).

Is input validation enough to prevent prototype pollution?

Input validation alone isn't sufficient—you must specifically reject or sanitize prototype-related keys. Modern libraries implement safe merging algorithms that prevent assignment to prototype chains regardless of input, which is the most effective defense.

Can static analysis detect prototype pollution?

Yes, static analysis tools like Semgrep and Trivy can detect prototype pollution vulnerabilities by identifying unsafe object merging patterns, use of `Object.assign()` with untrusted data, and missing prototype pollution guards. Trivy flagged this vulnerability in axios 1.12.0.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #7

Related Articles

high

How Arbitrary HTTP Header Injection via Prototype Pollution happens in JavaScript and how to fix it

A high-severity vulnerability (CVE-2026-42035) in axios version 1.13.5 allowed attackers to inject arbitrary HTTP headers through prototype pollution. The fix upgrades axios to version 1.18.0 in the frontend's dependency tree, which includes proper prototype chain validation when constructing HTTP request headers. This prevents attackers from manipulating outgoing requests to perform SSRF, session hijacking, or cache poisoning attacks.

high

How prototype pollution happens in Node.js HTTP clients and how to fix it

A prototype pollution vulnerability in Axios 1.15.1 could allow attackers to manipulate HTTP requests and disclose sensitive information. This vulnerability affects the Node.js sandbox environment used by the agent and was fixed by upgrading to Axios 1.15.2. The fix prevents attackers from poisoning object prototypes to intercept or modify request behavior.

high

How HTTP Transport Hijacking via Prototype Pollution happens in Node.js axios and how to fix it

CVE-2026-42033 is a high-severity prototype pollution vulnerability in axios versions prior to 1.15.1 that could allow attackers to hijack HTTP transport configuration through malicious input. This vulnerability affects any Node.js application using vulnerable axios versions to make HTTP requests. The fix involves upgrading axios to version 1.15.1, which patches the prototype pollution flaw and prevents transport layer attacks.

critical

How JSON request validation bypass happens in Node.js API handlers and how to fix it

A critical validation bypass in the `/api/agents/jobs` endpoint allowed attackers to send malformed JSON with arbitrary properties that could trigger prototype pollution or unexpected behavior. The fix added comprehensive validation checks including array detection and property existence verification to prevent malicious payloads from reaching downstream processing logic.

high

How prototype pollution via `__proto__` key happens in Node.js defu and how to fix it

A high-severity prototype pollution vulnerability (CVE-2026-35209) was discovered in the `defu` package version 6.1.4, which allowed attackers to inject properties into JavaScript's `Object.prototype` via the `__proto__` key in defaults arguments. The fix upgrades `defu` to version 6.1.5 in the frontend's dependency tree, protecting downstream consumers like `c12` and `dotenv` configuration loaders from malicious property injection.

critical

How Sensitive Data Exposure in Error Logging happens in TypeScript/Deno and how to fix it

A critical vulnerability in Supabase Edge Functions allowed sensitive authentication errors and API credentials to leak through verbose error logging. The `cancel-subscription/index.ts` function logged full error objects to the console, potentially exposing Paddle API keys and auth tokens in deployment logs. The fix sanitizes all error messages to log only safe error text while preserving debugging capability.