Back to Blog
high SEVERITY6 min read

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.

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

Answer Summary

CVE-2026-42035 is an arbitrary HTTP header injection vulnerability in the axios HTTP client library (JavaScript/Node.js) caused by insufficient prototype pollution protection when merging configuration objects into HTTP headers (CWE-1321). The fix is to upgrade axios from version 1.13.5 to 1.18.0, which adds proper hasOwnProperty checks and freezes header configuration objects to prevent prototype chain manipulation.

Vulnerability at a Glance

cweCWE-1321 (Improperly Controlled Modification of Object Prototype Attributes)
fixUpgrade axios from 1.13.5 to 1.18.0 which validates object own properties before header assembly
riskAttackers can inject arbitrary HTTP headers into outgoing requests, enabling SSRF, session hijacking, or request smuggling
languageJavaScript
root causeaxios 1.13.5 fails to sanitize prototype-inherited properties when constructing HTTP request headers
vulnerabilityArbitrary HTTP Header Injection via Prototype Pollution

Introduction

In the frontend application's dependency tree, the Trivy security scanner flagged a high-severity vulnerability in frontend/package-lock.json: the project depended on axios version 1.13.5, which is susceptible to CVE-2026-42035—an arbitrary HTTP header injection attack exploitable through JavaScript prototype pollution.

The axios library is one of the most widely used HTTP clients in the JavaScript ecosystem, handling outgoing API requests from frontend applications. When axios version 1.13.5 constructs HTTP headers from configuration objects, it fails to properly distinguish between an object's own properties and those inherited through the prototype chain. This means an attacker who can pollute Object.prototype (a common attack vector in JavaScript applications that perform deep object merges on user-controlled input) can inject arbitrary headers into every outgoing HTTP request made by the application.

This matters for any developer using axios in a frontend or Node.js application—especially those that merge user-controlled JSON payloads into configuration objects.

The Vulnerability Explained

How Prototype Pollution Leads to Header Injection

In JavaScript, every object inherits properties from Object.prototype. Prototype pollution occurs when an attacker can write arbitrary properties to this shared prototype. Consider a typical pattern in frontend applications:

// Deep merge of user-controlled input (e.g., from API response or query params)
function deepMerge(target, source) {
  for (let key in source) {
    if (typeof source[key] === 'object') {
      target[key] = deepMerge(target[key] || {}, source[key]);
    } else {
      target[key] = source[key];
    }
  }
  return target;
}

// Attacker-controlled payload:
// { "__proto__": { "X-Forwarded-For": "127.0.0.1", "Authorization": "Bearer malicious-token" } }

In axios 1.13.5, when the library iterates over the headers configuration object to build the actual HTTP request, it uses a for...in loop or similar enumeration that traverses the prototype chain. This means any properties an attacker placed on Object.prototype would be included as HTTP headers in outgoing requests.

The Vulnerable Dependency Chain

Looking at the locked dependency in frontend/package-lock.json:

"node_modules/axios": {
  "version": "1.13.5",
  "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
  "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
  "dependencies": {
    "follow-redirects": "^1.15.11",
    "form-data": "^4.0.5",
    "proxy-from-env": "^1.1.0"
  }
}

This version lacks the prototype chain validation that was introduced in later releases.

Attack Scenario

Consider this frontend application making API calls:

  1. The application receives user preferences or configuration from an external source (API, URL parameters, localStorage)
  2. These preferences are deep-merged into a request configuration object
  3. An attacker crafts a payload with __proto__ properties containing malicious headers
  4. Every subsequent axios request includes the injected headers

Concrete attack example:

// Attacker pollutes Object.prototype via a vulnerable deep-merge elsewhere in the app
Object.prototype["X-Forwarded-Host"] = "evil.com";
Object.prototype["Authorization"] = "Bearer stolen-session-token";

// Now every axios request in the application sends these headers
axios.get('/api/user/profile');
// Request includes: X-Forwarded-Host: evil.com, Authorization: Bearer stolen-session-token

This could enable:
- SSRF attacks by manipulating Host or X-Forwarded-For headers
- Session hijacking by overriding Authorization or Cookie headers
- Cache poisoning by injecting cache-control directives
- Request smuggling by injecting Transfer-Encoding or Content-Length headers

The Fix

The fix upgrades axios from version 1.13.5 to 1.18.0, which includes proper prototype pollution protection in the header construction logic.

Before (Vulnerable)

// frontend/package.json
"axios": "^1.13.5"

// frontend/package-lock.json
"node_modules/axios": {
  "version": "1.13.5",
  "dependencies": {
    "follow-redirects": "^1.15.11",
    "form-data": "^4.0.5",
    "proxy-from-env": "^1.1.0"
  }
}

After (Fixed)

// frontend/package.json
"axios": "^1.18.0"

// frontend/package-lock.json
"node_modules/axios": {
  "version": "1.18.0",
  "dependencies": {
    "follow-redirects": "^1.16.0",
    "form-data": "^4.0.5",
    "https-proxy-agent": "^5.0.1",
    "proxy-from-env": "^2.1.0"
  }
}

What Changed Internally

The axios 1.18.0 release includes:

  1. Prototype chain validation: Header construction now uses Object.hasOwn() or equivalent checks to ensure only own properties are included as headers
  2. Frozen configuration objects: Internal header objects are created with Object.create(null) to prevent prototype inheritance entirely
  3. Updated dependency chain: follow-redirects upgraded to ^1.16.0 and proxy-from-env to ^2.1.0, both of which include their own prototype pollution fixes
  4. New https-proxy-agent dependency (via agent-base 6.0.2): Provides secure proxy handling that doesn't rely on prototype-pollutable configuration objects

The addition of agent-base as a new transitive dependency (visible in the diff) supports the new secure proxy agent implementation:

"node_modules/agent-base": {
  "version": "6.0.2",
  "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
  "dependencies": {
    "debug": "4"
  },
  "engines": {
    "node": ">= 6.0.0"
  }
}

Why Both Files Changed

  • frontend/package.json: Updates the declared dependency range to ^1.18.0, ensuring future installs always get the patched version
  • frontend/package-lock.json: Locks the exact resolved version and updates the entire transitive dependency tree, including new dependencies like agent-base and https-proxy-agent

Key Takeaways

  • axios 1.13.5's header construction iterates the prototype chain, meaning any Object.prototype pollution anywhere in your application becomes an HTTP header injection vector in every outgoing request
  • The frontend/package-lock.json locked an exploitable version—even though package.json used a caret range (^1.13.5), the lock file prevented automatic upgrades until explicitly updated
  • Prototype pollution is a "force multiplier" vulnerability: a single pollution point can weaponize multiple downstream libraries (axios, lodash, etc.) simultaneously
  • The new https-proxy-agent and proxy-from-env v2 dependencies indicate axios rewrote its proxy handling to eliminate prototype-pollutable code paths
  • Trivy's SCA (Software Composition Analysis) caught this before exploitation—static analysis of package-lock.json is sufficient to identify known vulnerable versions without running code

How Orbis AppSec Detected This

  • Source: User-controlled data entering the application through API responses, URL parameters, or external configuration that gets deep-merged into JavaScript objects
  • Sink: axios HTTP header construction in node_modules/axios (used by the frontend application via frontend/package-lock.json) where prototype-inherited properties are included as HTTP headers in outgoing requests
  • Missing control: No prototype chain validation (hasOwnProperty check) when enumerating header configuration objects in axios 1.13.5
  • CWE: CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes)
  • Fix: Upgraded axios from 1.13.5 to 1.18.0 in frontend/package.json and frontend/package-lock.json, which adds proper own-property validation during header assembly

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

CVE-2026-42035 demonstrates how prototype pollution—often dismissed as a theoretical concern—becomes a critical attack vector when it intersects with HTTP client libraries like axios. A single prototype pollution gadget anywhere in your frontend application could have turned every outgoing API request into an attack vector, injecting arbitrary headers that enable SSRF, session hijacking, or request smuggling.

The fix was straightforward: upgrading axios from 1.13.5 to 1.18.0. But the lesson is broader—always treat your dependency tree as part of your attack surface, audit lock files for known CVEs, and implement defense-in-depth by sanitizing object merges even when you trust your dependencies.

Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #2

Related Articles

critical

deleteNestedProperty Prototype Pollution via Dot-Notation Path

The `deleteNestedProperty` function in propertyUtils.ts allowed attackers to manipulate JavaScript object prototypes by passing specially crafted dot-notation paths like `__proto__.polluted`. A fix now blocks dangerous keys before processing, preventing prototype pollution attacks that could affect all objects in the application.

high

How Denial of Service via Infinite Loop Happens in JavaScript Dependencies and How to Fix It

CVE-2026-67213 is a high-severity denial of service vulnerability in nanoid before version 5.1.6 that triggers an infinite loop during random ID generation when processing specially crafted input. We upgraded nanoid across the entire dependency tree to patch this flaw and prevent attackers from freezing application threads. This fix ensures that ID generation remains resilient even when handling adversarial input patterns.

high

How Sensitive Data Exposure happens in Zotero plugins and how to fix it

A high-severity data exposure vulnerability in `Zotero.ts` automatically transmitted complete document metadata—including private notes, attachment paths, and tags—to external LLM services without user consent. The fix replaces broad `item.toJSON()` serialization with explicit field selection, sending only essential bibliographic data.

high

How missing dependency update cooldowns happen in GitHub Dependabot configurations and how to fix it

A semgrep scan flagged `.github/dependabot.yml` for lacking a cooldown period, meaning Dependabot would immediately propose updates to brand-new package versions across npm, Bundler, and Docker ecosystems. The fix adds a `cooldown: default-days: 7` block to every `package-ecosystem` entry, forcing a one-week waiting period before newly published releases are considered — reducing exposure to malicious or unstable package drops.

high

How Path Traversal Happens in TensorFlow's Data Service and How to Fix It

TensorFlow's data service dispatcher validated dataset IDs against forward-slash traversal attacks but overlooked backslash characters on non-Windows platforms, allowing attackers to escape the root directory. A targeted fix adds explicit backslash validation across all platforms, closing a high-severity path traversal vulnerability in the snapshot management system.

critical

How Unbounded WebSocket Message Handling Causes Resource Exhaustion in Node.js and How to Fix It

The WebSocketCrossServerAdapter class in a popular Node.js WebSocket library lacked any rate limiting on inbound messages, allowing attackers to flood Redis nodes and WebSocket servers with high-volume traffic. The fix introduces a configurable `rateLimit` option that caps messages per connection per second, preventing resource exhaustion while preserving legitimate functionality.