CVE-2023-45857
Description
An issue discovered in Axios 1.5.1 inadvertently reveals the confidential XSRF-TOKEN stored in cookies by including it in the HTTP header X-XSRF-TOKEN for every request made to any host allowing attackers to view sensitive information.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Axios 1.5.1 leaks the XSRF-TOKEN cookie value into the X-XSRF-TOKEN header for requests to any host, enabling potential attackers to obtain the token.
Vulnerability
Overview
CVE-2023-45857 affects Axios version 1.5.1, a popular Promise-based HTTP client for the browser and Node.js [1]. The issue is that the library inadvertently includes the value of the confidential XSRF-TOKEN cookie in the X-XSRF-TOKEN HTTP header for every request, regardless of the target host [2]. This behavior violates the principle that the XSRF token should only be sent to the same origin that set the cookie, as cross-origin requests could expose the token to malicious sites.
Exploitation
Prerequisites
An attacker can exploit this vulnerability by luring a user to visit a malicious web page that makes cross-origin requests to any host. Since Axios automatically attaches the X-XSRF-TOKEN header with the cookie value, the attacker can observe that header if they control the target server or can inspect traffic (e.g., via an open Wi-Fi network). No additional authentication or user interaction beyond normal browsing is required—the token is leaked on every request made by the vulnerable client.
Impact and
Consequences
Successful exploitation allows an attacker to steal the XSRF token, which is used to protect against cross-site request forgery attacks. With the token in hand, the attacker can craft forged requests that appear legitimate to the victim’s authenticated session, potentially performing actions on the user’s behalf without their consent [2]. The sensitivity of the exposed information depends on the context of the application using Axios, but it directly undermines CSRF protections.
Mitigation
Status
The vulnerability has been patched by the Axios maintainers. The fix introduces a new withXSRFToken option that defaults to false, meaning Axios will no longer automatically set the XSRF token header unless the developer explicitly enables it [3][4]. For older 0.x branches, a similar backport is available [3]. Users should update to a patched version and review their usage of the withXSRFToken option to maintain desired behavior safely.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
axiosnpm | >= 1.0.0, < 1.6.0 | 1.6.0 |
axiosnpm | >= 0.8.1, < 0.28.0 | 0.28.0 |
Affected products
49- Axios/Axiosdescription
- osv-coords48 versionspkg:apk/chainguard/opensearch-dashboards-2pkg:apk/chainguard/opensearch-dashboards-2-alerting-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-anomaly-detection-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-compatpkg:apk/chainguard/opensearch-dashboards-2-configpkg:apk/chainguard/opensearch-dashboards-2-dashboards-mapspkg:apk/chainguard/opensearch-dashboards-2-dashboards-notificationspkg:apk/chainguard/opensearch-dashboards-2-dashboards-observabilitypkg:apk/chainguard/opensearch-dashboards-2-dashboards-query-workbenchpkg:apk/chainguard/opensearch-dashboards-2-dashboards-reportingpkg:apk/chainguard/opensearch-dashboards-2-dashboards-search-relevancepkg:apk/chainguard/opensearch-dashboards-2-dashboards-visualizationspkg:apk/chainguard/opensearch-dashboards-2-fipspkg:apk/chainguard/opensearch-dashboards-2-fips-alerting-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-fips-anomaly-detection-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-fips-configpkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-mapspkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-notificationspkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-observabilitypkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-query-workbenchpkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-reportingpkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-search-relevancepkg:apk/chainguard/opensearch-dashboards-2-fips-dashboards-visualizationspkg:apk/chainguard/opensearch-dashboards-2-fips-index-management-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-fips-ml-commons-dashboardspkg:apk/chainguard/opensearch-dashboards-2-fips-security-analytics-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-fips-security-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-index-management-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-ml-commons-dashboardspkg:apk/chainguard/opensearch-dashboards-2-security-analytics-dashboards-pluginpkg:apk/chainguard/opensearch-dashboards-2-security-dashboards-pluginpkg:apk/wolfi/opensearch-dashboards-2pkg:apk/wolfi/opensearch-dashboards-2-alerting-dashboards-pluginpkg:apk/wolfi/opensearch-dashboards-2-anomaly-detection-dashboards-pluginpkg:apk/wolfi/opensearch-dashboards-2-compatpkg:apk/wolfi/opensearch-dashboards-2-configpkg:apk/wolfi/opensearch-dashboards-2-dashboards-mapspkg:apk/wolfi/opensearch-dashboards-2-dashboards-notificationspkg:apk/wolfi/opensearch-dashboards-2-dashboards-observabilitypkg:apk/wolfi/opensearch-dashboards-2-dashboards-query-workbenchpkg:apk/wolfi/opensearch-dashboards-2-dashboards-reportingpkg:apk/wolfi/opensearch-dashboards-2-dashboards-search-relevancepkg:apk/wolfi/opensearch-dashboards-2-dashboards-visualizationspkg:apk/wolfi/opensearch-dashboards-2-index-management-dashboards-pluginpkg:apk/wolfi/opensearch-dashboards-2-ml-commons-dashboardspkg:apk/wolfi/opensearch-dashboards-2-security-analytics-dashboards-pluginpkg:apk/wolfi/opensearch-dashboards-2-security-dashboards-pluginpkg:npm/axios
< 2.11.1-r2+ 47 more
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.13.0-r0
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: < 2.11.1-r2
- (no CPE)range: >= 1.0.0, < 1.6.0
Patches
22755df562b9cfix(security): fixed CVE-2023-45857 by backporting `withXSRFToken` option to v0.x (#6091)
7 files changed · +96 −25
.github/workflows/ci.yml+1 −1 modified@@ -24,5 +24,5 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm - - run: npm install + - run: npm ci - run: npm test
index.d.ts+1 −0 modified@@ -165,6 +165,7 @@ export interface AxiosRequestConfig<D = any> { FormData?: new (...args: any[]) => object; }; formSerializer?: FormSerializerOptions; + withXSRFToken?: boolean | ((config: AxiosRequestConfig) => boolean | undefined); } export interface HeadersDefaults {
lib/adapters/xhr.js+8 −6 modified@@ -18,6 +18,7 @@ module.exports = function xhrAdapter(config) { var requestData = config.data; var requestHeaders = config.headers; var responseType = config.responseType; + var withXSRFToken = config.withXSRFToken; var onCanceled; function done() { if (config.cancelToken) { @@ -145,12 +146,13 @@ module.exports = function xhrAdapter(config) { // Specifically not if we're in a web worker, or react-native. if (utils.isStandardBrowserEnv()) { // Add xsrf header - var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ? - cookies.read(config.xsrfCookieName) : - undefined; - - if (xsrfValue) { - requestHeaders[config.xsrfHeaderName] = xsrfValue; + withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(config)); + if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(fullPath))) { + // Add xsrf header + var xsrfValue = config.xsrfHeaderName && config.xsrfCookieName && cookies.read(config.xsrfCookieName); + if (xsrfValue) { + requestHeaders[config.xsrfHeaderName] = xsrfValue; + } } }
lib/core/mergeConfig.js+1 −0 modified@@ -73,6 +73,7 @@ module.exports = function mergeConfig(config1, config2) { 'timeout': defaultToConfig2, 'timeoutMessage': defaultToConfig2, 'withCredentials': defaultToConfig2, + 'withXSRFToken': defaultToConfig2, 'adapter': defaultToConfig2, 'responseType': defaultToConfig2, 'xsrfCookieName': defaultToConfig2,
package.json+1 −1 modified@@ -5,7 +5,7 @@ "main": "index.js", "types": "index.d.ts", "scripts": { - "test": "node bin/ssl_hotfix.js grunt test && node bin/ssl_hotfix.js dtslint", + "test": "node bin/ssl_hotfix.js grunt test && node bin/ssl_hotfix.js dtslint --localTs node_modules/typescript/lib", "start": "node ./sandbox/server.js", "preversion": "grunt version && npm test", "build": "cross-env NODE_ENV=production grunt build",
README.md+3 −0 modified@@ -399,6 +399,9 @@ These are the available config options for making requests. Only the `url` is re // `xsrfHeaderName` is the name of the http header that carries the xsrf token value xsrfHeaderName: 'X-XSRF-TOKEN', // default + // `undefined` (default) - set XSRF header only for the same origin requests + withXSRFToken: boolean | undefined | ((config: AxiosRequestConfig) => boolean | undefined), + // `onUploadProgress` allows handling of progress events for uploads // browser only onUploadProgress: function (progressEvent) {
test/specs/xsrf.spec.js+81 −17 modified@@ -1,82 +1,146 @@ +'use strict'; + var cookies = require('../../lib/helpers/cookies'); -describe('xsrf', function () { - beforeEach(function () { +describe('xsrf', function() { + beforeEach(function() { jasmine.Ajax.install(); }); - afterEach(function () { + afterEach(function() { document.cookie = axios.defaults.xsrfCookieName + '=;expires=' + new Date(Date.now() - 86400000).toGMTString(); jasmine.Ajax.uninstall(); }); - it('should not set xsrf header if cookie is null', function (done) { + it('should not set xsrf header if cookie is null', function(done) { axios('/foo'); - getAjaxRequest().then(function (request) { + getAjaxRequest().then(function(request) { expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); done(); }); }); - it('should set xsrf header if cookie is set', function (done) { + it('should set xsrf header if cookie is set', function(done) { document.cookie = axios.defaults.xsrfCookieName + '=12345'; axios('/foo'); - getAjaxRequest().then(function (request) { + getAjaxRequest().then(function(request) { expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual('12345'); done(); }); }); - it('should not set xsrf header if xsrfCookieName is null', function (done) { + it('should not set xsrf header if xsrfCookieName is null', function(done) { document.cookie = axios.defaults.xsrfCookieName + '=12345'; axios('/foo', { xsrfCookieName: null }); - getAjaxRequest().then(function (request) { + getAjaxRequest().then(function(request) { expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); done(); }); }); - it('should not read cookies at all if xsrfCookieName is null', function (done) { - spyOn(cookies, "read"); + it('should not read cookies at all if xsrfCookieName is null', function(done) { + spyOn(cookies, 'read'); axios('/foo', { xsrfCookieName: null }); - getAjaxRequest().then(function (request) { + getAjaxRequest().then(function() { expect(cookies.read).not.toHaveBeenCalled(); done(); }); }); - it('should not set xsrf header for cross origin', function (done) { + it('should not set xsrf header for cross origin', function(done) { document.cookie = axios.defaults.xsrfCookieName + '=12345'; axios('http://example.com/'); - getAjaxRequest().then(function (request) { + getAjaxRequest().then(function(request) { expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); done(); }); }); - it('should set xsrf header for cross origin when using withCredentials', function (done) { + it('should set xsrf header for cross origin when using withCredentials and withXSRFToken', function(done) { document.cookie = axios.defaults.xsrfCookieName + '=12345'; axios('http://example.com/', { - withCredentials: true + withCredentials: true, + withXSRFToken: true }); - getAjaxRequest().then(function (request) { + getAjaxRequest().then(function(request) { expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual('12345'); done(); }); }); + describe('withXSRFToken option', function() { + it('should set xsrf header for cross origin when withXSRFToken = true', function(done) { + var token = '12345'; + + document.cookie = axios.defaults.xsrfCookieName + '=' + token; + + axios('http://example.com/', { + withXSRFToken: true + }); + + getAjaxRequest().then(function(request) { + expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(token); + done(); + }); + }); + + it('should not set xsrf header for the same origin when withXSRFToken = false', function(done) { + var token = '12345'; + + document.cookie = axios.defaults.xsrfCookieName + '=' + token; + + axios('/foo', { + withXSRFToken: false + }); + + getAjaxRequest().then(function(request) { + expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); + done(); + }); + }); + + it('should not set xsrf header for the same origin when withXSRFToken = false', function(done) { + var token = '12345'; + + document.cookie = axios.defaults.xsrfCookieName + '=' + token; + + axios('/foo', { + withXSRFToken: false + }); + + getAjaxRequest().then(function(request) { + expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); + done(); + }); + }); + + it('should support function resolver', function(done) { + var token = '12345'; + + document.cookie = axios.defaults.xsrfCookieName + '=' + token; + axios('/foo', { + withXSRFToken: function(config) { return config.userFlag === 'yes';}, + userFlag: 'yes' + }); + + getAjaxRequest().then(function(request) { + expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(token); + done(); + }); + }); + }); });
96ee232bd3eefix(CSRF): fixed CSRF vulnerability CVE-2023-45857 (#6028)
2 files changed · +4 −4
lib/adapters/xhr.js+2 −2 modified@@ -188,8 +188,8 @@ export default isXHRAdapterSupported && function (config) { // Specifically not if we're in a web worker, or react-native. if (platform.isStandardBrowserEnv) { // Add xsrf header - const xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) - && config.xsrfCookieName && cookies.read(config.xsrfCookieName); + // regarding CVE-2023-45857 config.withCredentials condition was removed temporarily + const xsrfValue = isURLSameOrigin(fullPath) && config.xsrfCookieName && cookies.read(config.xsrfCookieName); if (xsrfValue) { requestHeaders.set(config.xsrfHeaderName, xsrfValue);
test/specs/xsrf.spec.js+2 −2 modified@@ -67,15 +67,15 @@ describe('xsrf', function () { }); }); - it('should set xsrf header for cross origin when using withCredentials', function (done) { + it('should not set xsrf header for cross origin when using withCredentials', function (done) { document.cookie = axios.defaults.xsrfCookieName + '=12345'; axios('http://example.com/', { withCredentials: true }); getAjaxRequest().then(function (request) { - expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual('12345'); + expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); done(); }); });
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
13- github.com/advisories/GHSA-wf5p-g6vw-rhxxghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-45857ghsaADVISORY
- github.com/axios/axios/commit/2755df562b9c194fba6d8b609a383443f6a6e967ghsaWEB
- github.com/axios/axios/commit/96ee232bd3ee4de2e657333d4d2191cd389e14d0ghsaWEB
- github.com/axios/axios/issues/6006ghsaWEB
- github.com/axios/axios/issues/6022ghsaWEB
- github.com/axios/axios/pull/6028ghsaWEB
- github.com/axios/axios/pull/6091ghsaWEB
- github.com/axios/axios/releases/tag/v0.28.0ghsaWEB
- github.com/axios/axios/releases/tag/v1.6.0ghsaWEB
- security.netapp.com/advisory/ntap-20240621-0006ghsaWEB
- security.snyk.io/vuln/SNYK-JS-AXIOS-6032459ghsaWEB
- security.netapp.com/advisory/ntap-20240621-0006/mitre
News mentions
0No linked articles in our index yet.