TL;DR
- Axios has two new medium-severity issues our scanner checks for:
- Versions below 0.33.0: nested Axios option objects can consume polluted prototype values.
- Versions below 1.18.0: excessive recursion in
formDataToJSONcan cause denial of service. - Upgrade to Axios 0.33.0 or 1.18.0 (depending on your major line) to remove risk.
- If you are a FrameScan customer, your next scheduled scan already includes detections for both.
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
- If you are on the 0.x line of Axios and see
< 0.33.0in your lockfile, upgrade to 0.33.0: - npm:
npm install axios@0.33.0 - Yarn:
yarn add axios@0.33.0 - pnpm:
pnpm add axios@0.33.0 - If you are on the 1.x line of Axios and see
< 1.18.0, upgrade to 1.18.0: - npm:
npm install axios@1.18.0 - Yarn:
yarn add axios@1.18.0 - pnpm:
pnpm add axios@1.18.0 - Official advisory links: [MISSING: advisory link]
Call to action
- Existing customers: review findings and schedule a re-scan at https://framescan.io/scan
- New to FrameScan? Your first scan per verified domain is free: https://framescan.io/#pricing