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
•Technically reviewed by Anupam Mediratta•Published August 26, 2026•Reviewed 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.


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.


Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #70

Related Articles

high

CVE-2026-4800: lodash Template Imports Allow Code Execution

CVE-2026-4800 affects lodash's `_.template()` templating API, where untrusted input reaching the `imports` option can lead to arbitrary code execution. The fix was shipped as a dependency upgrade from lodash 4.17.21 to 4.18.1 in the project's lockfile, though the PR itself notes it was never verified against the actual code paths in this repository.

critical

proxy-addr 2.0.7 IP Spoofing: CVE-2026-90711 Trust Bypass

A critical vulnerability in proxy-addr 2.0.7 allowed attackers to spoof client IP addresses by manipulating X-Forwarded-For headers when the trust chain evaluation contained specific misconfigurations. The fix in version 2.0.8 hardens the trust evaluation logic to prevent IP address falsification in Express.js applications relying on this common middleware dependency.

high

TweenMax `_applyCycle` Prototype Pollution via vars.cycle Keys

A bundled copy of the TweenMax animation library copied attacker-influenceable `vars.cycle` property names straight onto a tween configuration object using an unguarded `for...in` loop, so a key named `__proto__`, `constructor`, or `prototype` was written through to the object's prototype chain. The fix adds an explicit key denylist to both copies of the `_applyCycle` helper so those three names are skipped during the merge. No CVE or GHSA is assigned; the issue is tracked as CWE-1321 (Improperl

high

picomatch 2.3.1 ReDoS: Extglob Pattern Catastrophic Backtracking

picomatch versions below 2.3.2, 3.0.2, or 4.0.4 contain a Regular Expression Denial of Service vulnerability in extglob pattern parsing. An attacker can cause catastrophic backtracking with patterns containing nested alternations and quantifiers, freezing any Node.js process that evaluates untrusted glob expressions.

critical

pet-window.js Dynamic Code Evaluation: CWE-94 Hardening via Number

The pet-window module constructed dynamic JavaScript by embedding raw configuration values into code strings. An attacker with local access could inject arbitrary JavaScript by modifying stored configuration. The fix replaces string interpolation with explicit Number() coercion and NaN validation for all numeric configuration parameters.

high

sanitizeUnicodeInput(): Fullwidth U+ Bypasses Codepoint Validation

The `sanitizeUnicodeInput()` helper used by the project character-range settings screen rewrote `U+` prefixes to `0x` and called `parseInt()`, but never normalized its argument first. Compatibility-equivalent forms such as fullwidth `U+`, superscript digits, or mathematical alphanumerics never matched the `/U\+/gi` regex, fell through to the `else return inputString` branch, and were handed back to callers verbatim as "sanitized" values. The fix inserts a `String.prototype.normalize('NFKC')` pas