FRAMESCAN
← Blog

Axios vulnerabilities: prototype-polluted options (<0.33.0) and DoS via formDataToJSON (<1.18.0)

FrameScan · 2026-07-22

TL;DR

At-a-glance

ID (official advisory) Impact Severity Affected versions Fixed version
axios < 0.33.0 — Axios: Nested axios option objects can consume polluted prototype values Prototype pollution may alter request options medium < 0.33.0 0.33.0
axios < 1.18.0 — Axios: Excessive recursion in formDataToJSON can cause denial of service Recursion in JSON conversion can crash process medium < 1.18.0 1.18.0

axios < 0.33.0 — Nested option objects can consume polluted prototype values

An attacker who can influence objects used to build Axios options may cause unexpected request behavior. That could mean altered headers, timeouts, or other settings that degrade reliability or enable secondary issues. Update promptly; while not labeled critical, it is safety-relevant for any app handling untrusted input.

Technical details

Summary data indicates Axios nested option objects could consume properties from polluted prototypes. When application code merges user-controlled objects into Axios config, inherited properties (e.g., via __proto__ pollution elsewhere in the app) may be treated as trusted options.

Illustrative example — not Axios source:

// Vulnerable pattern (illustrative): merging untrusted options directly
function makeRequest(axios, userOptions) {
  // userOptions may have inherited properties via a polluted prototype
  const config = {
    method: 'get',
    url: 'https://api.example.com/data',
    // Shallow spread copies enumerable props, including inherited ones in some patterns
    ...userOptions
  };
  return axios(config);
}

// Fixed pattern: sanitize and copy only known, own, safe keys
function makeSafeRequest(axios, userOptions) {
  const SAFE_KEYS = new Set(['url', 'method', 'headers', 'params', 'data', 'timeout']);
  const cfg = Object.create(null);
  const src = userOptions && typeof userOptions === 'object' ? userOptions : {};

  for (const key of Object.keys(src)) {
    if (SAFE_KEYS.has(key)) {
      cfg[key] = src[key];
    }
  }

  // Provide secure defaults; override only from cfg (own props only)
  const finalConfig = {
    method: 'get',
    url: 'https://api.example.com/data',
    headers: {},
    params: {},
    timeout: 5000,
    ...cfg
  };

  return axios(finalConfig);
}

The fix in Axios (0.33.0) prevents option resolution from consuming polluted prototype values. In app code, prefer copying only expected own properties from plain objects and avoid merging unvetted structures into transport configuration.

axios < 1.18.0 — Excessive recursion in formDataToJSON can cause denial of service

Applications that rely on Axios to transform FormData into JSON could hit excessive recursion and hang or crash the process when presented with deeply nested or cyclic data. This results in a denial of service under sustained triggering input. Upgrade is recommended as soon as your test cycle allows.

Technical details

The advisory summary points to unbounded recursion in formDataToJSON. Deeply nested structures or cycles can cause stack exhaustion or CPU spikes.

Illustrative example — not Axios source:

// Vulnerable pattern (illustrative): unbounded recursion
function toJSONUnsafe(value) {
  if (value instanceof Map) {
    const obj = {};
    for (const [k, v] of value) obj[k] = toJSONUnsafe(v);
    return obj;
  }
  if (Array.isArray(value)) return value.map(toJSONUnsafe);
  if (value && typeof value === 'object') {
    const out = {};
    for (const k of Object.keys(value)) out[k] = toJSONUnsafe(value[k]);
    return out;
  }
  return value;
}

// Fixed pattern: track depth and seen references to prevent runaway recursion
function toJSONSafe(value, opts = {}, state = { depth: 0, seen: new Set() }) {
  const { maxDepth = 1000 } = opts; // tune for your app
  if (state.depth > maxDepth) return null; // or throw, or truncate
  if (value && typeof value === 'object') {
    if (state.seen.has(value)) return null; // break cycles
    state.seen.add(value);
  }

  if (Array.isArray(value)) {
    return value.map(v => toJSONSafe(v, opts, { depth: state.depth + 1, seen: state.seen }));
  }

  if (value instanceof Map) {
    const obj = {};
    for (const [k, v] of value) {
      obj[k] = toJSONSafe(v, opts, { depth: state.depth + 1, seen: state.seen });
    }
    return obj;
  }

  if (value && typeof value === 'object') {
    const out = {};
    for (const k of Object.keys(value)) {
      out[k] = toJSONSafe(value[k], opts, { depth: state.depth + 1, seen: state.seen });
    }
    return out;
  }

  return value;
}

Axios 1.18.0 addresses the recursion risk internally. While upgrading, avoid passing attacker-controlled, arbitrarily deep, or cyclic structures into any JSON conversion utilities.

Remediation

Call to action

Is your site exposed? Scan it for $1