GHSA-PMV8-RQ9R-6J72

GHSA-PMV8-RQ9R-6J72 is a medium-severity uncontrolled resource consumption vulnerability in axios (npm), affecting versions >= 0.28.0, < 0.33.0. It is fixed in 0.33.0, 1.18.0.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

Axios: Deep formToJSON Key Recursion Can Cause Denial of Service

Axios versions starting with 0.28.0 contain uncontrolled recursion in formDataToJSON, which is exposed as axios.formToJSON() and used internally when axios serialises FormData with Content-Type: application/json.

If an application passes attacker-controlled FormData field names to this functionality, a field name with thousands of nested bracket segments can exhaust the JavaScript call stack and cause denial of service for that request or, in applications without appropriate error handling, process termination.

Affected Functionality

Affected functionality:

  • axios.formToJSON(formData)
  • Named ESM export formToJSON
  • Default transformRequest behaviour for FormData when Content-Type contains application/json

Unaffected functionality:

  • Normal multipart FormData submission without JSON serialisation
  • toFormData, which already enforces a maxDepth guard
  • Axios versions <=0.27.2, where formDataToJSON was not present

Technical Details

The vulnerable code is in lib/helpers/formDataToJSON.js.

parsePropPath() splits a field name such as a[x][x][x] into path segments. buildPath() then recursively processes one segment per call without enforcing a maximum depth:

const result = buildPath(path, value, target[name], index);

A key with thousands of bracket-delimited segments causes thousands of recursive calls and can exceed the JavaScript engine's call stack limit.

Relevant source locations:

  • lib/helpers/formDataToJSON.js contains the unbounded recursive buildPath().
  • lib/axios.js exposes the helper as axios.formToJSON.
  • index.js exposes formToJSON as a named export.
  • index.d.ts and index.d.cts declare the public API.
  • lib/defaults/index.js calls formDataToJSON(data) when JSON-serializing FormData.

The inverse helper, toFormData, already enforces maxDepth and throws AxiosError with ERR_FORM_DATA_DEPTH_EXCEEDED, but formDataToJSON does not have an equivalent guard.

Proof of Concept of Attack

import axios from 'axios';

const fd = new FormData();
fd.append('a' + '[x]'.repeat(15000), 'value');

try {
  axios.formToJSON(fd);
  console.log('not vulnerable');
} catch (e) {
  console.log(`${e.constructor.name}: ${e.message}`);
}

Expected result on affected versions:

RangeError: Maximum call stack size exceeded

The same condition can be reached via an axios request transformation when attacker-controlled FormData is sent with Content-Type: application/json.

Workarounds

Applications can reject or normalise untrusted form field names before calling axios.formToJSON().

Applications can avoid sending untrusted FormData through axios as JSON unless JSON conversion is required.

Applications should catch errors around formToJSON() or axios requests that transform untrusted FormData.

Original Source

An uncontrolled recursion vulnerability in formDataToJSON allows any user who controls FormData input to crash a Node.js process with a single request. The function recurses once per bracket-delimited segment in a FormData key name with no depth limit, so a key like a[x][x][x]... with 15,000+ segments exhausts the call stack. This is a denial-of-service that kills the process via an unrecoverable RangeError. The inverse function toFormData already enforces a maxDepth limit (default 100) for exactly this reason, formDataToJSON lacks the equivalent guard.

Details

Vulnerable function: buildPath in lib/helpers/formDataToJSON.js, lines 50–82.

buildPath(path, value, target, index) is called recursively, once per segment in the parsed property path, with no depth check:

// lib/helpers/formDataToJSON.js, lines 50–82
function buildPath(path, value, target, index) {
  let name = path[index++];              // advance one level
  if (name === '__proto__') return true;
  // ...
  if (!isLast) {
    // ...
    const result = buildPath(path, value, target[name], index);  // recurse, NO depth guard
    // ...
  }
}

The key is first split into segments by parsePropPath (line 17), which extracts every [segment] via regex. A key with 15,000 bracket pairs produces a 15,001-element array, causing 15,001 recursive calls, well beyond the V8 default stack limit (~10,000–15,000 frames).

formDataToJSON is a public API consumed two ways:

  1. Directly by consumers, exported as axios.formToJSON() (lib/axios.js:80), with TypeScript declarations in both index.d.ts:699 and index.d.cts:708, and documented in the API reference in four languages (docs/pages/advanced/api-reference.md).

  2. Internally by transformRequest, called at lib/defaults/index.js:56 when the request body is FormData and Content-Type contains application/json:

    return hasJSONContentType ? JSON.stringify(formDataToJSON(data)) : data;
    

Contrast with toFormData: The inverse function (lib/helpers/toFormData.js:118) enforces maxDepth (default 100) and throws AxiosError with code ERR_FORM_DATA_DEPTH_EXCEEDED when exceeded. formDataToJSON has no equivalent protection.

PoC

Requires only Node.js and an unmodified axios v1.x install:

import formDataToJSON from 'axios/lib/helpers/formDataToJSON.js';

// Build a FormData with a single key containing 15,000 nested bracket segments
const fd = new FormData();
const key = "a" + "[x]".repeat(15000);
fd.append(key, "value");

try {
  formDataToJSON(fd);
  console.log("Not vulnerable");
} catch (e) {
  console.log(e.constructor.name + ": " + e.message);
  // RangeError: Maximum call stack size exceeded
}

Verified output on Node.js 22.22.3 against axios v1.16.1 (current v1.x HEAD):

RangeError: Maximum call stack size exceeded

The process crashes. In a server context (e.g., Express middleware calling axios.formToJSON() on an uploaded form), a single crafted request terminates the process.

Impact

Denial of Service (process crash). Any unauthenticated user who can submit FormData to a Node.js application that passes it through axios.formToJSON(), or that sends it as a JSON-serialized FormData body via axios, can crash the server process with a single request. The RangeError from stack exhaustion is unrecoverable in many contexts (it cannot be reliably caught when the stack is already full). No authentication or special privileges are required; the attacker only needs to control a FormData key name.

Impact

Applications are affected only when untrusted users can control FormData key names that are converted through axios.

Affected paths include direct use of axios.formToJSON() on untrusted FormData and axios requests in which attacker-controlled FormData is sent with Content-Type: application/json.

The observed failure is RangeError: Maximum call stack size exceeded. In local testing, this error is catchable, so process-wide crash depends on the consuming application's error handling and runtime behaviour.

Crafted input forces the application to consume excessive CPU, memory, or other resources, degrading or denying service. Typical impact: denial of service.

Affected versions

axios (>= 0.28.0, < 0.33.0) axios (>= 1.0.0, < 1.18.0)

Security releases

axios → 0.33.0 (npm) axios → 1.18.0 (npm)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Upgrade the following packages to resolve this vulnerability:

axios to 0.33.0 or later; axios to 1.18.0 or later

Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.

Frequently Asked Questions

  1. What is GHSA-PMV8-RQ9R-6J72? GHSA-PMV8-RQ9R-6J72 is a medium-severity uncontrolled resource consumption vulnerability in axios (npm), affecting versions >= 0.28.0, < 0.33.0. It is fixed in 0.33.0, 1.18.0. Crafted input forces the application to consume excessive CPU, memory, or other resources, degrading or denying service.
  2. Which versions of axios are affected by GHSA-PMV8-RQ9R-6J72? axios (npm) versions >= 0.28.0, < 0.33.0 is affected.
  3. Is there a fix for GHSA-PMV8-RQ9R-6J72? Yes. GHSA-PMV8-RQ9R-6J72 is fixed in 0.33.0, 1.18.0. Upgrade to this version or later.
  4. Is GHSA-PMV8-RQ9R-6J72 exploitable, and should I be worried? Whether GHSA-PMV8-RQ9R-6J72 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  5. What actually determines whether GHSA-PMV8-RQ9R-6J72 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  6. How do I fix GHSA-PMV8-RQ9R-6J72?
    • Upgrade axios to 0.33.0 or later
    • Upgrade axios to 1.18.0 or later

Other vulnerabilities in axios

Stop the waste.
Protect your environment with Kodem.