GHSA-42H9-826W-CGV3: Root-Cause Fix for Axios formDataToJSON Recursion DoS
Summary
Axios addressed the reported denial-of-service condition in formDataToJSON by adding an explicit nesting-depth guard before recursive path construction. The patch throws AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED once parsed form key depth exceeds 100, preventing stack exhaustion from attacker-controlled deeply nested field names. The same change set also includes broader hardening for prototype-pollution-safe config reads and related request-path validation, but the recursion issue itself appears directly and specifically fixed at the parser entry point.
Analysis
Vulnerability
GHSA-42H9-826W-CGV3 describes a denial-of-service condition in Axios where formDataToJSON recursively materializes object paths from attacker-controlled form field names. In the vulnerable flow, the parser called buildPath(parsePropPath(name), value, obj, 0) without bounding nesting depth, so a single request containing a deeply nested key such as repeated [x] segments could drive unbounded recursion and crash a Node.js process via stack exhaustion. The advisory summary and the patch diff in pull request #11001 and commit 1417285c69344bbcc6420a021f67dee0c6fedb2d align on this root cause.
// vulnerable behavior in lib/helpers/formDataToJSON.js
buildPath(parsePropPath(name), value, obj, 0);The exploitability is straightforward because the recursion depth is derived from input structure rather than authenticated state or server-side resource ownership. Any application path that accepts multipart or form-like input and invokes this helper can be forced into pathological recursion.
Patch
The fix in #11001 adds an explicit depth limit in lib/helpers/formDataToJSON.js. The parser now imports AxiosError, defines MAX_FORM_DATA_TO_JSON_DEPTH = 100, computes depth from the parsed property path, and rejects over-deep inputs before entering recursive object construction. The associated unit test in commit 1417285c69344bbcc6420a021f67dee0c6fedb2d verifies that a field name with 101 nested segments throws ERR_FORM_DATA_DEPTH_EXCEEDED instead of overflowing the stack.
var AxiosError = require('../core/AxiosError');
var MAX_FORM_DATA_TO_JSON_DEPTH = 100;
function assertPathDepth(path) {
var depth = path.length - 1;
if (depth > MAX_FORM_DATA_TO_JSON_DEPTH) {
throw new AxiosError(
'Maximum object depth of ' + MAX_FORM_DATA_TO_JSON_DEPTH + ' exceeded (got ' + depth + ' levels)',
AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED
);
}
}
var path = parsePropPath(name);
assertPathDepth(path);
buildPath(path, value, obj, 0);The same patch train also adds a depth assertion in toFormData, plus multiple prototype-pollution-safe property reads in adapters and URL-building helpers. Those changes are security hardening, but they are orthogonal to the recursion DoS itself. Relevant source references are pull request #11001, commit 1417285c69344bbcc6420a021f67dee0c6fedb2d, and the advisory at GitHub Security Advisory.
Review
Pros
- The mitigation is placed at the correct choke point: immediately after
parsePropPath(name)and before recursive descent. That directly addresses the uncontrolled recursion primitive rather than relying on downstream behavior. - The failure mode is explicit and typed. Throwing
AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDEDgives callers a deterministic signal instead of a generic runtime stack overflow. - The test coverage is relevant and exploit-shaped. The new unit test constructs a nested field name generator and asserts rejection at depth 101, demonstrating prevention before stack exhaustion.
- The patch also mirrors the same depth-control concept in
toFormData, reducing asymmetry between serialization and deserialization paths.
Cons
- The chosen limit of 100 is a policy decision with no rationale in the provided sources. It is likely safe, but compatibility impact for legitimate deeply nested payloads is not discussed.
- The guard only constrains path depth, not total field count or aggregate object expansion cost. Extremely broad but shallow inputs may still be expensive, though that is a different resource-consumption class than the reported recursion crash.
- The patch bundle mixes several unrelated hardening changes. While beneficial overall, that increases review surface and can obscure the minimal fix for this advisory.
Verdict
Root-cause.
This patch fixes the reported issue at its source by bounding attacker-controlled nesting before buildPath recurses. The vulnerable behavior was not merely an unsafe exception path or adapter-specific normalization issue; it was the absence of a recursion-depth constraint in formDataToJSON. The added assertPathDepth check directly neutralizes that condition, and the regression test demonstrates the intended pre-overflow rejection behavior. Based on the supplied sources, this is a complete and technically appropriate remediation for the GHSA-described DoS vector.
Recommended Labs
Try this vulnerability pattern yourself with hands-on labs.
- Pollution.js
Closest hands-on JavaScript defensive lab for this Axios parser issue. While the GHSA is a denial-of-service flaw caused by uncontrolled recursion in nested form key parsing, this lab trains the same core secure-coding defenses: strict input handling, safe parsing of attacker-controlled HTTP parameters, and hardening request-processing logic in a Node/JavaScript context.
- Property.js
Useful because the vulnerable Axios path involves unsafe handling of user-supplied nested keys. This lab focuses on defensive fixes around attacker-controlled object/property construction in JavaScript, which is highly relevant to preventing recursive parser abuse and other unsafe object-shaping bugs.
- OWASP Top 10
SecDim Play did not appear to have an exact DoS/uncontrolled-recursion lab for this Axios advisory. As a fallback hands-on starting point, this easy JavaScript challenge still reinforces defensive validation patterns. For structured learning that better complements this GHSA, pair these labs with the SecDim Learn OWASP Top 10 course at https://learn.secdim.com/course/owasp-top-10, especially the modules around secure input handling and resilient server-side code.