CVE-2025-62718
Description
Axios is a promise based HTTP client for the browser and Node.js. Prior to 1.15.0 and 0.31.0, Axios does not correctly handle hostname normalization when checking NO_PROXY rules. Requests to loopback addresses like localhost. (with a trailing dot) or [::1] (IPv6 literal) skip NO_PROXY matching and go through the configured proxy. This goes against what developers expect and lets attackers force requests through a proxy, even if NO_PROXY is set up to protect loopback or internal services. This issue leads to the possibility of proxy bypass and SSRF vulnerabilities allowing attackers to reach sensitive loopback or internal services despite the configured protections. This vulnerability is fixed in 1.15.0 and 0.31.0.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
axiosnpm | >= 1.0.0, < 1.15.0 | 1.15.0 |
axiosnpm | < 0.31.0 | 0.31.0 |
Affected products
1Patches
203cdfc99e8dbfix: backport the fixes from the v1 branch (#10688)
8 files changed · +397 −4
lib/adapters/http.js+7 −4 modified@@ -19,6 +19,7 @@ var platform = require('../platform'); var fromDataURI = require('../helpers/fromDataURI'); var stream = require('stream'); var estimateDataURLDecodedBytes = require('../helpers/estimateDataURLDecodedBytes.js'); +var shouldBypassProxy = require('../helpers/shouldBypassProxy'); var isHttps = /https:?/; @@ -46,9 +47,11 @@ function setProxy(options, configProxy, location) { if (!proxy && proxy !== false) { var proxyUrl = getProxyForUrl(location); if (proxyUrl) { - proxy = url.parse(proxyUrl); - // replace 'host' since the proxy object is not a URL object - proxy.host = proxy.hostname; + if (!shouldBypassProxy(location)) { + proxy = url.parse(proxyUrl); + // replace 'host' since the proxy object is not a URL object + proxy.host = proxy.hostname; + } } } if (proxy) { @@ -273,7 +276,7 @@ module.exports = function httpAdapter(config) { } else { options.hostname = parsed.hostname; options.port = parsed.port; - setProxy(options, config.proxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path); + setProxy(options, config.proxy, protocol + '//' + parsed.host + options.path); } var transport;
lib/core/dispatchRequest.js+5 −0 modified@@ -6,6 +6,7 @@ var isCancel = require('../cancel/isCancel'); var defaults = require('../defaults'); var CanceledError = require('../cancel/CanceledError'); var normalizeHeaderName = require('../helpers/normalizeHeaderName'); +var sanitizeHeaderValue = require('../helpers/sanitizeHeaderValue'); /** * Throws a `CanceledError` if cancellation has been requested. @@ -58,6 +59,10 @@ module.exports = function dispatchRequest(config) { } ); + utils.forEach(config.headers, function sanitizeHeaderConfigValue(value, header) { + config.headers[header] = sanitizeHeaderValue(value); + }); + var adapter = config.adapter || defaults.adapter; return adapter(config).then(function onAdapterResolution(response) {
lib/helpers/sanitizeHeaderValue.js+22 −0 added@@ -0,0 +1,22 @@ +'use strict'; + +var utils = require('../utils'); + +var INVALID_HEADER_VALUE_RE = /[^\x09\x20-\x7E\x80-\xFF]/g; +var BOUNDARY_WHITESPACE_RE = /^[\x09\x20]+|[\x09\x20]+$/g; + +function sanitizeHeaderValue(value) { + if (value === false || value == null) { + return value; + } + + if (utils.isArray(value)) { + return value.map(sanitizeHeaderValue); + } + + return String(value) + .replace(INVALID_HEADER_VALUE_RE, '') + .replace(BOUNDARY_WHITESPACE_RE, ''); +} + +module.exports = sanitizeHeaderValue;
lib/helpers/shouldBypassProxy.js+133 −0 added@@ -0,0 +1,133 @@ +'use strict'; + +var URL = require('url').URL; + +var DEFAULT_PORTS = { + http: 80, + https: 443, + ws: 80, + wss: 443, + ftp: 21 +}; + +function parseNoProxyEntry(entry) { + var entryHost = entry; + var entryPort = 0; + + if (entryHost.charAt(0) === '[') { + var bracketIndex = entryHost.indexOf(']'); + + if (bracketIndex !== -1) { + var host = entryHost.slice(1, bracketIndex); + var rest = entryHost.slice(bracketIndex + 1); + + if (rest.charAt(0) === ':' && /^\d+$/.test(rest.slice(1))) { + entryPort = parseInt(rest.slice(1), 10); + } + + return [host, entryPort]; + } + } + + var firstColon = entryHost.indexOf(':'); + var lastColon = entryHost.lastIndexOf(':'); + + if (firstColon !== -1 && firstColon === lastColon && /^\d+$/.test(entryHost.slice(lastColon + 1))) { + entryPort = parseInt(entryHost.slice(lastColon + 1), 10); + entryHost = entryHost.slice(0, lastColon); + } + + return [entryHost, entryPort]; +} + +function normalizeNoProxyHost(hostname) { + if (!hostname) { + return hostname; + } + + if (hostname.charAt(0) === '[' && hostname.charAt(hostname.length - 1) === ']') { + hostname = hostname.slice(1, -1); + } + + return hostname.replace(/\.+$/, ''); +} + +function isLoopbackIPv4(hostname) { + var octets = hostname.split('.'); + + if (octets.length !== 4) { + return false; + } + + if (octets[0] !== '127') { + return false; + } + + return octets.every(function testOctet(octet) { + return /^\d+$/.test(octet) && Number(octet) >= 0 && Number(octet) <= 255; + }); +} + +function isLoopbackHost(hostname) { + return hostname === 'localhost' || hostname === '::1' || isLoopbackIPv4(hostname); +} + +module.exports = function shouldBypassProxy(location) { + var parsed; + + try { + parsed = new URL(location); + } catch (err) { + return false; + } + + var noProxy = (process.env.no_proxy || process.env.NO_PROXY || '').toLowerCase(); + + if (!noProxy) { + return false; + } + + if (noProxy === '*') { + return true; + } + + var protocol = parsed.protocol.split(':', 1)[0]; + var port = parsed.port !== '' ? parseInt(parsed.port, 10) : (DEFAULT_PORTS[protocol] || 0); + var hostname = normalizeNoProxyHost(parsed.hostname.toLowerCase()); + + return noProxy.split(/[\s,]+/).some(function testNoProxyEntry(entry) { + if (!entry) { + return false; + } + + var entryParts = parseNoProxyEntry(entry); + var entryHost = normalizeNoProxyHost(entryParts[0]); + var entryPort = entryParts[1]; + + if (entryHost === '*') { + return true; + } + + if (!entryHost) { + return false; + } + + if (entryPort && entryPort !== port) { + return false; + } + + if (isLoopbackHost(hostname) && isLoopbackHost(entryHost)) { + return true; + } + + if (entryHost.charAt(0) === '*') { + entryHost = entryHost.slice(1); + } + + if (entryHost.charAt(0) === '.') { + return hostname.slice(-entryHost.length) === entryHost; + } + + return hostname === entryHost; + }); +};
test/specs/headers.spec.js+13 −0 modified@@ -112,4 +112,17 @@ describe('headers', function () { done(); }); }); + + it('should sanitize headers containing invalid characters', function (done) { + axios('/foo', { + headers: { + 'x-test': ' ok\r\nInjected: yes\t' + } + }); + + getAjaxRequest().then(function (request) { + testHeaderValue(request.requestHeaders, 'x-test', 'okInjected: yes'); + done(); + }); + }); });
test/unit/adapters/http.js+123 −0 modified@@ -31,8 +31,39 @@ describe('supports http with nodejs', function () { proxy = null; } delete process.env.http_proxy; + delete process.env.HTTP_PROXY; delete process.env.https_proxy; delete process.env.no_proxy; + delete process.env.NO_PROXY; + }); + + it('should sanitize request headers containing invalid characters', function (done) { + server = http.createServer(function (req, res) { + res.setHeader('Content-Type', 'text/plain'); + res.end(req.headers['x-test']); + }).listen(4444, function () { + axios.get('http://localhost:4444/', { + headers: { + 'x-test': ' ok\r\nInjected: yes\t' + } + }).then(function (response) { + assert.equal(response.data, 'okInjected: yes'); + done(); + }).catch(done); + }); + }); + + it('should preserve request error for unavailable host with invalid characters', function (done) { + axios.get('http://localhost:1/', { + headers: { + 'x-test': 'ok\r\nInjected: yes' + } + }).then(function () { + done(new Error('request should not succeed')); + }).catch(function (error) { + assert.notEqual(error.message, 'Invalid character in header content ["x-test"]'); + done(); + }); }); it('should throw an error if the timeout property is not parsable as a number', function (done) { @@ -967,6 +998,98 @@ describe('supports http with nodejs', function () { }); }); + it('should not use proxy for localhost with trailing dot when listed in no_proxy', function (done) { + var proxyRequests = 0; + + proxy = http.createServer(function (request, response) { + proxyRequests += 1; + response.end('proxied'); + }).listen(4000, function () { + process.env.http_proxy = 'http://localhost:4000/'; + process.env.HTTP_PROXY = 'http://localhost:4000/'; + process.env.no_proxy = 'localhost,127.0.0.1,::1'; + process.env.NO_PROXY = 'localhost,127.0.0.1,::1'; + + axios.get('http://localhost.:1/', { + timeout: 100 + }).then(function () { + done(new Error('request should not succeed')); + }).catch(function () { + assert.equal(proxyRequests, 0, 'should not use proxy for localhost with trailing dot'); + done(); + }); + }); + }); + + it('should not use proxy for bracketed IPv6 loopback when listed in no_proxy', function (done) { + var proxyRequests = 0; + + proxy = http.createServer(function (request, response) { + proxyRequests += 1; + response.end('proxied'); + }).listen(4000, function () { + process.env.http_proxy = 'http://localhost:4000/'; + process.env.HTTP_PROXY = 'http://localhost:4000/'; + process.env.no_proxy = 'localhost,127.0.0.1,::1'; + process.env.NO_PROXY = 'localhost,127.0.0.1,::1'; + + axios.get('http://[::1]:1/', { + timeout: 100 + }).then(function () { + done(new Error('request should not succeed')); + }).catch(function () { + assert.equal(proxyRequests, 0, 'should not use proxy for IPv6 loopback'); + done(); + }); + }); + }); + + it('should not use proxy for 127.0.0.1 when no_proxy is localhost', function (done) { + var proxyRequests = 0; + + proxy = http.createServer(function (request, response) { + proxyRequests += 1; + response.end('proxied'); + }).listen(4000, function () { + process.env.http_proxy = 'http://localhost:4000/'; + process.env.HTTP_PROXY = 'http://localhost:4000/'; + process.env.no_proxy = 'localhost'; + process.env.NO_PROXY = 'localhost'; + + axios.get('http://127.0.0.1:1/', { + timeout: 100 + }).then(function () { + done(new Error('request should not succeed')); + }).catch(function () { + assert.equal(proxyRequests, 0, 'should not use proxy for IPv4 loopback alias'); + done(); + }); + }); + }); + + it('should not use proxy for [::1] when no_proxy is localhost', function (done) { + var proxyRequests = 0; + + proxy = http.createServer(function (request, response) { + proxyRequests += 1; + response.end('proxied'); + }).listen(4000, function () { + process.env.http_proxy = 'http://localhost:4000/'; + process.env.HTTP_PROXY = 'http://localhost:4000/'; + process.env.no_proxy = 'localhost'; + process.env.NO_PROXY = 'localhost'; + + axios.get('http://[::1]:1/', { + timeout: 100 + }).then(function () { + done(new Error('request should not succeed')); + }).catch(function () { + assert.equal(proxyRequests, 0, 'should not use proxy for IPv6 loopback alias'); + done(); + }); + }); + }); + it('should use proxy for domains not in no_proxy', function (done) { server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8');
test/unit/helpers/sanitizeHeaderValue.js+20 −0 added@@ -0,0 +1,20 @@ +var assert = require('assert'); +var sanitizeHeaderValue = require('../../../lib/helpers/sanitizeHeaderValue'); + +describe('helpers::sanitizeHeaderValue', function () { + it('should remove invalid header characters', function () { + assert.strictEqual(sanitizeHeaderValue('ok\r\nInjected: yes'), 'okInjected: yes'); + assert.strictEqual(sanitizeHeaderValue('ok\x01bad'), 'okbad'); + }); + + it('should remove boundary whitespace', function () { + assert.strictEqual(sanitizeHeaderValue(' value\t'), 'value'); + }); + + it('should sanitize array values recursively', function () { + assert.deepStrictEqual( + sanitizeHeaderValue([' safe=1 ', 'unsafe=1\nInjected: true']), + ['safe=1', 'unsafe=1Injected: true'] + ); + }); +});
test/unit/helpers/shouldBypassProxy.js+74 −0 added@@ -0,0 +1,74 @@ +var assert = require('assert'); +var shouldBypassProxy = require('../../../lib/helpers/shouldBypassProxy'); + +var originalNoProxy = process.env.no_proxy; +var originalNOProxy = process.env.NO_PROXY; + +function setNoProxy(value) { + process.env.no_proxy = value; + process.env.NO_PROXY = value; +} + +describe('helpers::shouldBypassProxy', function () { + afterEach(function () { + if (originalNoProxy === undefined) { + delete process.env.no_proxy; + } else { + process.env.no_proxy = originalNoProxy; + } + + if (originalNOProxy === undefined) { + delete process.env.NO_PROXY; + } else { + process.env.NO_PROXY = originalNOProxy; + } + }); + + it('should bypass proxy for localhost with a trailing dot', function () { + setNoProxy('localhost,127.0.0.1,::1'); + assert.strictEqual(shouldBypassProxy('http://localhost.:8080/'), true); + }); + + it('should bypass proxy for bracketed ipv6 loopback', function () { + setNoProxy('localhost,127.0.0.1,::1'); + assert.strictEqual(shouldBypassProxy('http://[::1]:8080/'), true); + }); + + it('should support bracketed ipv6 entries in no_proxy', function () { + setNoProxy('[::1]'); + assert.strictEqual(shouldBypassProxy('http://[::1]:8080/'), true); + }); + + it('should match wildcard and explicit ports', function () { + setNoProxy('*.example.com,localhost:8080'); + + assert.strictEqual(shouldBypassProxy('http://api.example.com/'), true); + assert.strictEqual(shouldBypassProxy('http://localhost:8080/'), true); + assert.strictEqual(shouldBypassProxy('http://localhost:8081/'), false); + }); + + it('should treat localhost and loopback IP aliases as equivalent', function () { + setNoProxy('localhost'); + + assert.strictEqual(shouldBypassProxy('http://127.0.0.1:8080/'), true); + assert.strictEqual(shouldBypassProxy('http://[::1]:8080/'), true); + + setNoProxy('127.0.0.1'); + + assert.strictEqual(shouldBypassProxy('http://localhost:8080/'), true); + assert.strictEqual(shouldBypassProxy('http://[::1]:8080/'), true); + + setNoProxy('::1'); + + assert.strictEqual(shouldBypassProxy('http://localhost:8080/'), true); + assert.strictEqual(shouldBypassProxy('http://127.0.0.1:8080/'), true); + }); + + it('should keep loopback alias matching port-aware', function () { + setNoProxy('localhost:8080'); + + assert.strictEqual(shouldBypassProxy('http://127.0.0.1:8080/'), true); + assert.strictEqual(shouldBypassProxy('http://[::1]:8080/'), true); + assert.strictEqual(shouldBypassProxy('http://127.0.0.1:8081/'), false); + }); +});
fb3befb6daacfix: no_proxy hostname normalization bypass leads to ssrf (#10661)
4 files changed · +270 −1
lib/adapters/http.js+4 −1 modified@@ -23,6 +23,7 @@ import formDataToStream from '../helpers/formDataToStream.js'; import readBlob from '../helpers/readBlob.js'; import ZlibHeaderTransformStream from '../helpers/ZlibHeaderTransformStream.js'; import callbackify from '../helpers/callbackify.js'; +import shouldBypassProxy from '../helpers/shouldBypassProxy.js'; import { progressEventReducer, progressEventDecorator, @@ -192,7 +193,9 @@ function setProxy(options, configProxy, location) { if (!proxy && proxy !== false) { const proxyUrl = getProxyForUrl(location); if (proxyUrl) { - proxy = new URL(proxyUrl); + if (!shouldBypassProxy(location)) { + proxy = new URL(proxyUrl); + } } } if (proxy) {
lib/helpers/shouldBypassProxy.js+106 −0 added@@ -0,0 +1,106 @@ +const DEFAULT_PORTS = { + http: 80, + https: 443, + ws: 80, + wss: 443, + ftp: 21, +}; + +const parseNoProxyEntry = (entry) => { + let entryHost = entry; + let entryPort = 0; + + if (entryHost.charAt(0) === '[') { + const bracketIndex = entryHost.indexOf(']'); + + if (bracketIndex !== -1) { + const host = entryHost.slice(1, bracketIndex); + const rest = entryHost.slice(bracketIndex + 1); + + if (rest.charAt(0) === ':' && /^\d+$/.test(rest.slice(1))) { + entryPort = Number.parseInt(rest.slice(1), 10); + } + + return [host, entryPort]; + } + } + + const firstColon = entryHost.indexOf(':'); + const lastColon = entryHost.lastIndexOf(':'); + + if ( + firstColon !== -1 && + firstColon === lastColon && + /^\d+$/.test(entryHost.slice(lastColon + 1)) + ) { + entryPort = Number.parseInt(entryHost.slice(lastColon + 1), 10); + entryHost = entryHost.slice(0, lastColon); + } + + return [entryHost, entryPort]; +}; + +const normalizeNoProxyHost = (hostname) => { + if (!hostname) { + return hostname; + } + + if (hostname.charAt(0) === '[' && hostname.charAt(hostname.length - 1) === ']') { + hostname = hostname.slice(1, -1); + } + + return hostname.replace(/\.+$/, ''); +}; + +export default function shouldBypassProxy(location) { + let parsed; + + try { + parsed = new URL(location); + } catch (_err) { + return false; + } + + const noProxy = (process.env.no_proxy || process.env.NO_PROXY || '').toLowerCase(); + + if (!noProxy) { + return false; + } + + if (noProxy === '*') { + return true; + } + + const port = + Number.parseInt(parsed.port, 10) || DEFAULT_PORTS[parsed.protocol.split(':', 1)[0]] || 0; + + const hostname = normalizeNoProxyHost(parsed.hostname.toLowerCase()); + + return noProxy.split(/[\s,]+/).some((entry) => { + if (!entry) { + return false; + } + + let [entryHost, entryPort] = parseNoProxyEntry(entry); + + entryHost = normalizeNoProxyHost(entryHost); + + if (!entryHost) { + return false; + } + + if (entryPort && entryPort !== port) { + return false; + } + + if (entryHost.charAt(0) === '*') { + entryHost = entryHost.slice(1); + } + + if (entryHost.charAt(0) === '.') { + return hostname.endsWith(entryHost); + } + + return hostname === entryHost; + }); +}
tests/unit/adapters/http.test.js+108 −0 modified@@ -1738,6 +1738,114 @@ describe('supports http with nodejs', () => { } }); + it('should not use proxy for localhost with trailing dot when listed in no_proxy', async () => { + const originalHttpProxy = process.env.http_proxy; + const originalHTTPProxy = process.env.HTTP_PROXY; + const originalNoProxy = process.env.no_proxy; + const originalNOProxy = process.env.NO_PROXY; + + let proxyRequests = 0; + const proxy = await startHTTPServer( + (_, response) => { + proxyRequests += 1; + response.end('proxied'); + }, + { port: PROXY_PORT } + ); + + const noProxyValue = 'localhost,127.0.0.1,::1'; + const proxyUrl = `http://localhost:${proxy.address().port}/`; + process.env.http_proxy = proxyUrl; + process.env.HTTP_PROXY = proxyUrl; + process.env.no_proxy = noProxyValue; + process.env.NO_PROXY = noProxyValue; + + try { + await assert.rejects(axios.get('http://localhost.:1/', { timeout: 100 })); + assert.equal(proxyRequests, 0, 'should not use proxy for localhost with trailing dot'); + } finally { + await stopHTTPServer(proxy); + + if (originalHttpProxy === undefined) { + delete process.env.http_proxy; + } else { + process.env.http_proxy = originalHttpProxy; + } + + if (originalHTTPProxy === undefined) { + delete process.env.HTTP_PROXY; + } else { + process.env.HTTP_PROXY = originalHTTPProxy; + } + + if (originalNoProxy === undefined) { + delete process.env.no_proxy; + } else { + process.env.no_proxy = originalNoProxy; + } + + if (originalNOProxy === undefined) { + delete process.env.NO_PROXY; + } else { + process.env.NO_PROXY = originalNOProxy; + } + } + }); + + it('should not use proxy for bracketed IPv6 loopback when listed in no_proxy', async () => { + const originalHttpProxy = process.env.http_proxy; + const originalHTTPProxy = process.env.HTTP_PROXY; + const originalNoProxy = process.env.no_proxy; + const originalNOProxy = process.env.NO_PROXY; + + let proxyRequests = 0; + const proxy = await startHTTPServer( + (_, response) => { + proxyRequests += 1; + response.end('proxied'); + }, + { port: PROXY_PORT } + ); + + const noProxyValue = 'localhost,127.0.0.1,::1'; + const proxyUrl = `http://localhost:${proxy.address().port}/`; + process.env.http_proxy = proxyUrl; + process.env.HTTP_PROXY = proxyUrl; + process.env.no_proxy = noProxyValue; + process.env.NO_PROXY = noProxyValue; + + try { + await assert.rejects(axios.get('http://[::1]:1/', { timeout: 100 })); + assert.equal(proxyRequests, 0, 'should not use proxy for IPv6 loopback'); + } finally { + await stopHTTPServer(proxy); + + if (originalHttpProxy === undefined) { + delete process.env.http_proxy; + } else { + process.env.http_proxy = originalHttpProxy; + } + + if (originalHTTPProxy === undefined) { + delete process.env.HTTP_PROXY; + } else { + process.env.HTTP_PROXY = originalHTTPProxy; + } + + if (originalNoProxy === undefined) { + delete process.env.no_proxy; + } else { + process.env.no_proxy = originalNoProxy; + } + + if (originalNOProxy === undefined) { + delete process.env.NO_PROXY; + } else { + process.env.NO_PROXY = originalNOProxy; + } + } + }); + it('should use proxy for domains not in no_proxy', async () => { const originalHttpProxy = process.env.http_proxy; const originalHTTPProxy = process.env.HTTP_PROXY;
tests/unit/helpers/shouldBypassProxy.test.js+52 −0 added@@ -0,0 +1,52 @@ +import { afterEach, describe, expect, it } from 'vitest'; +import shouldBypassProxy from '../../../lib/helpers/shouldBypassProxy.js'; + +const originalNoProxy = process.env.no_proxy; +const originalNOProxy = process.env.NO_PROXY; + +const setNoProxy = (value) => { + process.env.no_proxy = value; + process.env.NO_PROXY = value; +}; + +afterEach(() => { + if (originalNoProxy === undefined) { + delete process.env.no_proxy; + } else { + process.env.no_proxy = originalNoProxy; + } + + if (originalNOProxy === undefined) { + delete process.env.NO_PROXY; + } else { + process.env.NO_PROXY = originalNOProxy; + } +}); + +describe('helpers::shouldBypassProxy', () => { + it('should bypass proxy for localhost with a trailing dot', () => { + setNoProxy('localhost,127.0.0.1,::1'); + + expect(shouldBypassProxy('http://localhost.:8080/')).toBe(true); + }); + + it('should bypass proxy for bracketed ipv6 loopback', () => { + setNoProxy('localhost,127.0.0.1,::1'); + + expect(shouldBypassProxy('http://[::1]:8080/')).toBe(true); + }); + + it('should support bracketed ipv6 entries in no_proxy', () => { + setNoProxy('[::1]'); + + expect(shouldBypassProxy('http://[::1]:8080/')).toBe(true); + }); + + it('should match wildcard and explicit ports', () => { + setNoProxy('*.example.com,localhost:8080'); + + expect(shouldBypassProxy('http://api.example.com/')).toBe(true); + expect(shouldBypassProxy('http://localhost:8080/')).toBe(true); + expect(shouldBypassProxy('http://localhost:8081/')).toBe(false); + }); +});
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
11- github.com/axios/axios/commit/03cdfc99e8db32a390e12128208b6778492cee9cnvdPatchWEB
- github.com/axios/axios/commit/fb3befb6daac6cad26b2e54094d0f2d9e47f24dfnvdPatchWEB
- github.com/axios/axios/pull/10661nvdIssue TrackingPatchWEB
- github.com/axios/axios/security/advisories/GHSA-3p68-rc4w-qgx5nvdExploitMitigationVendor AdvisoryWEB
- github.com/advisories/GHSA-3p68-rc4w-qgx5ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-62718ghsaADVISORY
- datatracker.ietf.org/doc/html/rfc1034nvdTechnical DescriptionWEB
- datatracker.ietf.org/doc/html/rfc3986nvdTechnical DescriptionWEB
- github.com/axios/axios/pull/10688nvdIssue TrackingWEB
- github.com/axios/axios/releases/tag/v0.31.0nvdRelease NotesWEB
- github.com/axios/axios/releases/tag/v1.15.0nvdProductRelease NotesWEB
News mentions
0No linked articles in our index yet.