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:
- The application receives user preferences or configuration from an external source (API, URL parameters, localStorage)
- These preferences are deep-merged into a request configuration object
- An attacker crafts a payload with
__proto__properties containing malicious headers - 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:
- Prototype chain validation: Header construction now uses
Object.hasOwn()or equivalent checks to ensure only own properties are included as headers - Frozen configuration objects: Internal header objects are created with
Object.create(null)to prevent prototype inheritance entirely - Updated dependency chain:
follow-redirectsupgraded to^1.16.0andproxy-from-envto^2.1.0, both of which include their own prototype pollution fixes - New
https-proxy-agentdependency (viaagent-base6.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 versionfrontend/package-lock.json: Locks the exact resolved version and updates the entire transitive dependency tree, including new dependencies likeagent-baseandhttps-proxy-agent
Prevention & Best Practices
For Application Developers
- Never deep-merge untrusted input without sanitization: If you must merge user-controlled objects, strip
__proto__,constructor, andprototypekeys first:
function safeMerge(target, source) {
const BLACKLIST = ['__proto__', 'constructor', 'prototype'];
for (let key of Object.keys(source)) {
if (BLACKLIST.includes(key)) continue;
target[key] = source[key];
}
return target;
}
-
Use
Object.create(null)for configuration maps: Objects without a prototype can't be polluted through the prototype chain. -
Freeze critical objects: Use
Object.freeze()on configuration objects that shouldn't be modified at runtime.
For Dependency Management
- Enable automated dependency scanning: Use Trivy, Snyk, or Dependabot to catch known CVEs in your dependency tree
- Pin exact versions in lock files: Always commit your
package-lock.jsonand review changes to it - Audit transitive dependencies: Vulnerabilities often hide in indirect dependencies
Security Standards
- CWE-1321: Improperly Controlled Modification of Object Prototype Attributes
- OWASP: This falls under A06:2021 – Vulnerable and Outdated Components
- CWE-113: Improper Neutralization of CRLF Sequences in HTTP Headers (related impact)
Key Takeaways
- axios 1.13.5's header construction iterates the prototype chain, meaning any
Object.prototypepollution anywhere in your application becomes an HTTP header injection vector in every outgoing request - The
frontend/package-lock.jsonlocked an exploitable version—even thoughpackage.jsonused 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-agentandproxy-from-envv2 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.jsonis 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 viafrontend/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.jsonandfrontend/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.
References
- CWE-1321: Improperly Controlled Modification of Object Prototype Attributes
- CWE-113: Improper Neutralization of CRLF Sequences in HTTP Headers
- OWASP Prototype Pollution Prevention Cheat Sheet
- axios Official Documentation
- Semgrep Prototype Pollution Rules
- fix: upgrade axios to 1.15.1, 0.31.1 (CVE-2026-42035)