Back to Blog
high SEVERITY8 min read

How HTTP Transport Hijacking via Prototype Pollution happens in JavaScript and how to fix it

CVE-2026-42033 is a high-severity prototype pollution vulnerability in axios that allows attackers to hijack the HTTP transport layer used by the library. The deltamod project was running axios 1.14.0, which lacked the hardened transport configuration introduced in 1.18.0 — including an explicit `https-proxy-agent` dependency and an upgraded `follow-redirects` floor. Upgrading to axios 1.18.0 closes the attack surface by ensuring that object prototype manipulation cannot silently redirect or int

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

Answer Summary

CVE-2026-42033 is a high-severity prototype pollution vulnerability (CWE-1321) in the axios JavaScript HTTP client that enables HTTP Transport Hijacking. In versions prior to 1.15.1/1.18.0, an attacker who can influence JavaScript object properties can pollute `Object.prototype` to override axios's internal transport adapter, silently redirecting or intercepting all outbound HTTP requests made by the application. The fix is to upgrade axios to 1.18.0 (or 1.15.1 for the 0.x branch), which introduces explicit `https-proxy-agent` handling and raises the `follow-redirects` floor to `^1.16.0`, preventing prototype-inherited properties from substituting the legitimate transport agent.

Vulnerability at a Glance

cweCWE-1321
fixUpgrade axios from 1.14.0 to 1.18.0; adds explicit https-proxy-agent and raises follow-redirects floor to ^1.16.0
riskAttacker can redirect or intercept all outbound HTTP/HTTPS requests made by the application
languageJavaScript / Node.js
root causeaxios resolved its HTTP transport adapter from object properties without guarding against prototype-inherited values
vulnerabilityHTTP Transport Hijacking via Prototype Pollution

How HTTP Transport Hijacking via Prototype Pollution Happens in JavaScript and How to Fix It


The Problem in Plain Sight: A Dependency That Became a Liability

The package-lock.json file in the deltamod project locked axios at version 1.14.0. On the surface, that looks unremarkable — a pinned dependency doing its job. But Trivy's static analysis flagged it as CVE-2026-42033, a high-severity vulnerability that could allow an attacker to silently redirect every outbound HTTP request the application makes. The fix was a version bump, but understanding why the old version was dangerous — and exactly what changed — is worth a close look.


The Vulnerability Explained

What Is Prototype Pollution?

JavaScript's prototype chain means that almost every object in a Node.js runtime ultimately inherits from Object.prototype. If an attacker can write an arbitrary key to Object.prototype, every plain object in the process will appear to have that key as an "own-like" property — unless the code explicitly guards against inherited values.

// Attacker-controlled input triggers this somewhere in the dependency tree:
Object.prototype.adapter = maliciousTransportAgent;

// Now, inside axios's transport resolution:
const config = {};
console.log(config.adapter); // → maliciousTransportAgent  ← NOT the real axios adapter

How Axios 1.14.0 Was Affected

In axios versions before the fix, the library resolved its HTTP transport adapter by reading the adapter (and related transport configuration) properties from the merged request config object. Because this lookup did not use Object.prototype.hasOwnProperty checks or Object.create(null) maps, a polluted prototype could inject a foreign value into the transport resolution path.

The vulnerable package-lock.json entry looked like this:

"node_modules/axios": {
  "version": "1.14.0",
  "resolved": "https://registry.npmjs.org/axios/-/axios-1.14.0.tgz",
  "integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==",
  "dependencies": {
    "follow-redirects": "^1.15.11",
    "form-data": "^4.0.5",
    "proxy-from-env": "^2.1.0"
  }
}

Two things stand out:

  1. No https-proxy-agent — there is no explicit, version-pinned HTTPS proxy agent. The transport layer for HTTPS connections was therefore resolved more loosely.
  2. follow-redirects floor at ^1.15.11 — this floor is below the version that introduced hardened prototype-pollution defenses in redirect handling.

The Attack Scenario

Imagine deltamod is a desktop application that fetches update manifests or patch metadata over HTTPS. An attacker who can influence any JavaScript object deserialization in the same process (e.g., via a malicious plugin, a crafted TOML config loaded through @std/toml, or a compromised transitive dependency) could execute:

// Somewhere in a malicious or compromised dependency:
const payload = JSON.parse('{"__proto__": {"adapter": "http"}}');
// Or more directly:
Object.prototype.httpsAgent = new http.Agent({ /* attacker proxy */ });

Once Object.prototype is polluted, the next time deltamod calls:

axios.get('https://update-server.example.com/manifest.json')

…axios's internal config merge produces an object that appears to have httpsAgent set to the attacker's proxy. All HTTPS traffic is now routed through that proxy, enabling:

  • Credential theft — any Authorization headers or tokens in requests are exposed.
  • Response tampering — the attacker can serve a malicious update manifest, potentially triggering a malicious binary download.
  • Data exfiltration — request bodies containing user data are intercepted silently.

For deltamod specifically — a tool that downloads and applies binary patches — a hijacked transport could mean the application installs attacker-controlled files.


The Fix

What Changed in package-lock.json

The pull request upgrades axios from 1.14.0 to 1.18.0. Here is the exact diff for the axios entry:

Before:

"node_modules/axios": {
  "version": "1.14.0",
  "resolved": "https://registry.npmjs.org/axios/-/axios-1.14.0.tgz",
  "integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==",
  "dependencies": {
    "follow-redirects": "^1.15.11",
    "form-data": "^4.0.5",
    "proxy-from-env": "^2.1.0"
  }
}

After:

"node_modules/axios": {
  "version": "1.18.0",
  "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz",
  "integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==",
  "dependencies": {
    "follow-redirects": "^1.16.0",
    "form-data": "^4.0.5",
    "https-proxy-agent": "^5.0.1",
    "proxy-from-env": "^2.1.0"
  }
},
"node_modules/axios/node_modules/agent-base": {
  "version": "6.0.2",
  "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
  "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
  "dependencies": {
    "debug": "4"
  },
  "engines": {
    "node": ">= 6.0.0"
  }
}

Why Each Change Matters

Change Security Significance
follow-redirects floor raised from ^1.15.11^1.16.0 follow-redirects 1.16.0 introduced its own prototype-pollution guards in redirect URL resolution, closing a secondary vector
https-proxy-agent: ^5.0.1 added as an explicit dependency axios now resolves the HTTPS transport agent from a declared, integrity-checked package rather than from a loosely inherited property
New agent-base@6.0.2 sub-dependency pinned Provides the underlying socket abstraction that https-proxy-agent uses; having it explicitly pinned prevents prototype-inherited agent-base substitution
package.json axios range updated from ^1.12.0^1.18.0 Ensures future npm install runs never resolve back to a vulnerable version

The Core Security Improvement

By making https-proxy-agent an explicit, integrity-verified dependency, axios 1.18.0 no longer needs to fall back to prototype-chain property lookup when constructing its HTTPS transport. The agent is imported directly:

// Conceptual representation of the fix inside axios internals:
// Before (vulnerable): agent resolved from config object — pollutable
const agent = config.httpsAgent; // could come from Object.prototype

// After (fixed): agent resolved from explicit, imported module
const { HttpsProxyAgent } = require('https-proxy-agent'); // explicit import
const agent = proxyUrl ? new HttpsProxyAgent(proxyUrl) : undefined;

This means even if Object.prototype.httpsAgent is polluted, axios ignores it in favor of the explicitly constructed agent.


Prevention & Best Practices

1. Guard Against Prototype Pollution in Your Own Code

When merging configuration objects, never use plain {} as a base if the source could be attacker-influenced:

// Vulnerable
const config = Object.assign({}, userInput, defaults);

// Safer
const config = Object.assign(Object.create(null), userInput, defaults);
// Or use structured clone:
const config = structuredClone(defaults);
Object.assign(config, sanitize(userInput));

2. Validate Own-Property Access

When reading security-sensitive properties from config objects:

// Vulnerable
const adapter = config.adapter;

// Safe
const adapter = Object.prototype.hasOwnProperty.call(config, 'adapter')
  ? config.adapter
  : defaultAdapter;

3. Pin and Audit Your Dependency Tree Regularly

The deltamod package.json had "axios": "^1.12.0" — a range that allowed any 1.x minor. While semver ranges are convenient, they mean a npm install on a fresh machine could resolve to any version in that range. After this fix, the range is ^1.18.0, which ensures the minimum resolved version is always patched.

# Run regularly in CI:
npm audit
npx better-npm-audit audit

# Or use Trivy directly:
trivy fs --scanners vuln package-lock.json

4. Use --ignore-scripts and Subresource Integrity

npm ci --ignore-scripts

This prevents malicious postinstall scripts from polluting prototypes during installation.

5. Consider --frozen-lockfile in Production

npm ci  # always uses package-lock.json exactly; never resolves ranges

Security Standards Reference

  • CWE-1321: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
  • OWASP A06:2021 – Vulnerable and Outdated Components
  • OWASP A08:2021 – Software and Data Integrity Failures

Key Takeaways

  • package-lock.json locking axios@1.14.0 was the direct root cause — a version range of ^1.12.0 in package.json silently allowed a vulnerable version to be installed for months.
  • The absence of an explicit https-proxy-agent dependency in axios 1.14.0 meant HTTPS transport resolution was vulnerable to prototype-inherited property injection — a subtle but critical gap.
  • Raising the follow-redirects floor from ^1.15.11 to ^1.16.0 closes a secondary prototype-pollution vector in redirect URL handling that would otherwise remain open even after the primary fix.
  • For deltamod specifically, the risk was concrete: a hijacked transport could have caused the application to download and apply attacker-controlled binary patches, leading to full system compromise.
  • Trivy's static analysis of package-lock.json caught this before exploitation — demonstrating the value of scanning lock files, not just source code.

How Orbis AppSec Detected This

  • Source: The tainted data entry point is any JavaScript object deserialization or merge operation within the deltamod process (or its dependency tree) that processes attacker-influenced input without prototype-pollution guards.
  • Sink: axios's internal transport adapter resolution, which reads httpsAgent and adapter from the merged request config object — properties that can be inherited from a polluted Object.prototype.
  • Missing control: axios 1.14.0 lacked an explicit https-proxy-agent import and did not perform hasOwnProperty checks before using transport-related config properties, allowing prototype-inherited values to substitute the legitimate transport agent.
  • CWE: CWE-1321 — Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
  • Fix: Upgraded axios from 1.14.0 to 1.18.0 in package-lock.json, adding an explicit https-proxy-agent@^5.0.1 dependency and raising the follow-redirects floor to ^1.16.0.

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-42033 is a reminder that prototype pollution is not just a theoretical concern — in a library as widely used as axios, it translates directly into HTTP transport hijacking that can silently redirect every outbound request your application makes. For deltamod, a tool that downloads and applies binary patches, that could have meant the difference between a legitimate update and a full system compromise.

The fix is straightforward: upgrade axios to 1.18.0. But the broader lesson is architectural — explicit dependency declarations, integrity hashes, and own-property guards are the layers that prevent prototype pollution from becoming transport hijacking. Keep your lock files audited, your dependency ranges tight, and your CI pipelines running npm audit and Trivy on every commit.


References

Frequently Asked Questions

What is HTTP Transport Hijacking via Prototype Pollution?

It is an attack where an adversary pollutes JavaScript's Object.prototype with a crafted property that axios reads when selecting its HTTP transport adapter, causing all outbound requests to be routed through an attacker-controlled agent instead of the legitimate one.

How do you prevent prototype pollution in JavaScript?

Use Object.create(null) for configuration maps, validate that resolved properties are own-properties (hasOwnProperty), freeze critical prototype chains, and keep HTTP client libraries patched to versions that perform these checks internally.

What CWE is prototype pollution?

Prototype pollution is classified as CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes).

Is input sanitization enough to prevent prototype pollution in axios?

Not on its own. The vulnerability exists inside axios's transport resolution logic, so sanitizing application-level user input does not protect against a malicious package or indirect dependency that has already polluted the prototype. Upgrading axios is required.

Can static analysis detect prototype pollution vulnerabilities?

Yes. Tools like Trivy (which flagged this issue), Semgrep, and Snyk can identify known-vulnerable package versions in package-lock.json and detect prototype pollution patterns in source code.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #70

Related Articles

high

How JavaScript Injection via String Interpolation Happens in Go Wails Applications and How to Fix It

A high-severity JavaScript injection vulnerability in `internal/clusterconfigs/input.go` allowed arbitrary code execution through malicious kubeconfig filenames. The `saveClusterConfigFile` function at line 20 constructed JavaScript code by directly interpolating unsanitized filenames into `window.ExecJS()` calls, enabling attackers to break out of string literals and execute arbitrary JavaScript in the Webview context.

high

How Denial of Service via Prototype Pollution happens in Axios and how to fix it

Axios versions prior to 1.15.1 merged untrusted configuration objects without guarding against the `__proto__` key, letting attacker-controlled input pollute `Object.prototype` and crash or destabilize applications. Upgrading axios (and its transitive dependencies `form-data`, `follow-redirects`, `proxy-from-env`) closes this Denial of Service and prototype-pollution attack surface without changing any application code.

critical

How Server-Side Request Forgery happens in Node.js and how to fix it

The order-flow service in a Node.js e-commerce backend built an outbound fetch() URL by directly concatenating a configurable `sendingOrder.url` value with a query string, with no validation of protocol or destination. This allowed order data—including customer and payment-adjacent information—to be silently redirected to an attacker-controlled endpoint simply by changing a config value or environment variable.

high

How Infinite Loop Denial of Service Happens in nanoid and How to Fix It

CVE-2026-67213 is a high-severity infinite loop vulnerability in nanoid's `customAlphabet` function that could cause Denial of Service through CPU exhaustion. The fix upgrades nanoid from 3.3.12 to patched versions 3.3.18 and 5.1.6, eliminating the loop condition that trapped ID generation when processing certain input patterns.

critical

How Message Corruption via Protocol Length Header Abuse Happens in WebSocket Implementations and How to Fix It

CVE-2026-54466 is a critical vulnerability in websocket-driver 0.7.4 that allows attackers to corrupt WebSocket messages by abusing protocol length headers. The fix upgrades the package to version 0.7.5, which implements proper validation of untrusted length header inputs. This vulnerability could allow attackers to modify or inject data into real-time communication channels used by frontend applications.

critical

How XML Entity Expansion happens in Node.js and how to fix it

A critical XML External Entity (XXE) vulnerability in `lib/xml2json.js` allowed attackers to trigger exponential memory consumption through nested entity expansion. The fix adds `strictEntities: true` to both SAX parser instances, disabling dangerous entity processing that could crash servers processing untrusted XML.