CVE-2024-39338
Description
axios 1.7.2 allows SSRF via unexpected behavior where requests for path relative URLs get processed as protocol relative URLs.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Axios 1.7.2 SSRF: path-relative URLs treated as protocol-relative, bypassing baseURL; fixed in 1.7.4.
Axios versions up to 1.7.2 contain a server-side request forgery (SSRF) vulnerability due to mishandling of path-relative URLs. When a baseURL is configured, the library incorrectly treats user-supplied paths beginning with a single slash as protocol-relative URLs if they start with a slash followed by a hostname-like pattern [4]. For example, a request to '/google.com' is interpreted as '//google.com', which the library resolves as a protocol-relative URL rather than a path relative to the baseURL [3].
An attacker who controls the path segment—such as a user ID parameter—can exploit this by supplying a value like '/internal-service' or '/attacker.com'. Since the baseURL is ignored, the request is made to the attacker-chosen host [4]. This bypasses the intended restriction that requests should remain within the baseURL domain, and the server makes the request as if it were a full absolute URL, leading to SSRF.
Impact: An attacker can make arbitrary HTTP requests from the server to internal networks, cloud metadata endpoints, or other sensitive resources. This could lead to information disclosure, internal service probing, or further compromise [4].
Mitigation: The vulnerability was fixed in axios version 1.7.4, released on or before June 24, 2024 [4]. The fix in pull request #6539 properly validates and rejects protocol-relative URLs when a baseURL is set [3]. Users should upgrade to 1.7.4 or later.
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.3.2, < 1.7.4 | 1.7.4 |
Affected products
62- axios/axiosdescription
- osv-coords61 versionspkg:apk/chainguard/airflow-2pkg:apk/chainguard/airflow-2-compatpkg:apk/chainguard/airflow-2-iamguarded-compatpkg:apk/chainguard/argo-workflow-clipkg:apk/chainguard/argo-workflow-controllerpkg:apk/chainguard/argo-workflow-controller-compatpkg:apk/chainguard/argo-workflow-executorpkg:apk/chainguard/argo-workflow-executor-compatpkg:apk/chainguard/argo-workflowspkg:apk/chainguard/argo-workflows-known-hostspkg:apk/chainguard/argo-workflows-uipkg:apk/chainguard/jitsucom-jitsupkg:apk/chainguard/jitsucom-jitsu-consolepkg:apk/chainguard/jitsucom-jitsu-rotorpkg:apk/chainguard/kibana-7pkg:apk/chainguard/kibana-7-bitnamipkg:apk/chainguard/kibana-8pkg:apk/chainguard/kibana-8-bitnamipkg:apk/chainguard/kibana-8-iamguardedpkg:apk/chainguard/kubeflow-centraldashboardpkg:apk/chainguard/kubeflow-pipelinespkg:apk/chainguard/kubeflow-pipelines-apiserverpkg:apk/chainguard/kubeflow-pipelines-cache-deployerpkg:apk/chainguard/kubeflow-pipelines-cache-deployer-compatpkg:apk/chainguard/kubeflow-pipelines-cache_serverpkg:apk/chainguard/kubeflow-pipelines-frontendpkg:apk/chainguard/kubeflow-pipelines-metadata-envoy-configpkg:apk/chainguard/kubeflow-pipelines-metadata-writerpkg:apk/chainguard/kubeflow-pipelines-metadata-writer-compatpkg:apk/chainguard/kubeflow-pipelines-persistence_agentpkg:apk/chainguard/kubeflow-pipelines-scheduledworkflowpkg:apk/chainguard/kubeflow-pipelines-viewer-crd-controllerpkg:apk/chainguard/lernapkg:apk/wolfi/argo-workflow-clipkg:apk/wolfi/argo-workflow-controllerpkg:apk/wolfi/argo-workflow-controller-compatpkg:apk/wolfi/argo-workflow-executorpkg:apk/wolfi/argo-workflow-executor-compatpkg:apk/wolfi/argo-workflowspkg:apk/wolfi/argo-workflows-known-hostspkg:apk/wolfi/argo-workflows-uipkg:apk/wolfi/jitsucom-jitsupkg:apk/wolfi/jitsucom-jitsu-consolepkg:apk/wolfi/jitsucom-jitsu-rotorpkg:apk/wolfi/kubeflow-centraldashboardpkg:apk/wolfi/kubeflow-pipelinespkg:apk/wolfi/kubeflow-pipelines-apiserverpkg:apk/wolfi/kubeflow-pipelines-cache-deployerpkg:apk/wolfi/kubeflow-pipelines-cache-deployer-compatpkg:apk/wolfi/kubeflow-pipelines-cache_serverpkg:apk/wolfi/kubeflow-pipelines-frontendpkg:apk/wolfi/kubeflow-pipelines-metadata-envoy-configpkg:apk/wolfi/kubeflow-pipelines-metadata-writerpkg:apk/wolfi/kubeflow-pipelines-metadata-writer-compatpkg:apk/wolfi/kubeflow-pipelines-persistence_agentpkg:apk/wolfi/kubeflow-pipelines-scheduledworkflowpkg:apk/wolfi/kubeflow-pipelines-viewer-crd-controllerpkg:apk/wolfi/lernapkg:npm/axiospkg:rpm/opensuse/pgadmin4&distro=openSUSE%20Leap%2015.6pkg:rpm/suse/pgadmin4&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Python%203%2015%20SP6
< 2.11.0-r15+ 60 more
- (no CPE)range: < 2.11.0-r15
- (no CPE)range: < 2.11.0-r15
- (no CPE)range: < 2.11.0-r15
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 2.8.0-r1
- (no CPE)range: < 2.8.0-r1
- (no CPE)range: < 2.8.0-r1
- (no CPE)range: < 7.17.24-r0
- (no CPE)range: < 7.17.24-r0
- (no CPE)range: < 8.17.3-r2
- (no CPE)range: < 8.17.3-r2
- (no CPE)range: < 8.17.3-r2
- (no CPE)range: < 1.9.0-r1
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 8.1.8-r1
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 3.6.5-r2
- (no CPE)range: < 2.8.0-r1
- (no CPE)range: < 2.8.0-r1
- (no CPE)range: < 2.8.0-r1
- (no CPE)range: < 1.9.0-r1
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 2.2.0-r10
- (no CPE)range: < 8.1.8-r1
- (no CPE)range: >= 1.3.2, < 1.7.4
- (no CPE)range: < 8.5-150600.3.6.1
- (no CPE)range: < 8.5-150600.3.6.1
Patches
2abd24a7367726b6b605eaf73fix(sec): CVE-2024-39338 (#6539) (#6543)
4 files changed · +47 −11
lib/adapters/http.js+1 −1 modified@@ -229,7 +229,7 @@ export default isHttpAdapterSupported && function httpAdapter(config) { // Parse url const fullPath = buildFullPath(config.baseURL, config.url); - const parsed = new URL(fullPath, 'http://localhost'); + const parsed = new URL(fullPath, utils.hasBrowserEnv ? platform.origin : undefined); const protocol = parsed.protocol || supportedProtocols[0]; if (protocol === 'data:') {
lib/helpers/isAbsoluteURL.js+2 −2 modified@@ -8,8 +8,8 @@ * @returns {boolean} True if the specified URL is absolute, otherwise false */ export default function isAbsoluteURL(url) { - // A URL is considered absolute if it begins with "<scheme>://". + // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL). // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed // by any combination of letters, digits, plus, period, or hyphen. - return /^([a-z][a-z\d+\-.]*:)\/\//i.test(url); + return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url); }
test/specs/helpers/isAbsoluteURL.spec.js+2 −2 modified@@ -12,8 +12,8 @@ describe('helpers::isAbsoluteURL', function () { expect(isAbsoluteURL('!valid://example.com/')).toBe(false); }); - it('should return false if URL is protocol-relative', function () { - expect(isAbsoluteURL('//example.com/')).toBe(false); + it('should return true if URL is protocol-relative', function () { + expect(isAbsoluteURL('//example.com/')).toBe(true); }); it('should return false if URL is relative', function () {
test/unit/regression/SNYK-JS-AXIOS-7361793.js+42 −6 modified@@ -4,6 +4,9 @@ import axios from '../../../index.js'; import http from 'http'; import assert from 'assert'; +import utils from '../../../lib/utils.js'; +import platform from '../../../lib/platform/index.js'; + const GOOD_PORT = 4666; const BAD_PORT = 4667; @@ -27,7 +30,7 @@ describe('Server-Side Request Forgery (SSRF)', () => { badServer.close(); }); - it('should not fetch bad server', async () => { + it('should not fetch in server-side mode', async () => { const ssrfAxios = axios.create({ baseURL: 'http://localhost:' + String(GOOD_PORT), }); @@ -36,10 +39,43 @@ describe('Server-Side Request Forgery (SSRF)', () => { // Malicious payload is as below. const userId = '/localhost:' + String(BAD_PORT); - const response = await ssrfAxios.get(`/${userId}`); - assert.strictEqual(response.data, 'good'); - assert.strictEqual(response.config.baseURL, 'http://localhost:' + String(GOOD_PORT)); - assert.strictEqual(response.config.url, '//localhost:' + String(BAD_PORT)); - assert.strictEqual(response.request.res.responseUrl, 'http://localhost:' + String(GOOD_PORT) + '/localhost:' + String(BAD_PORT)); + try { + await ssrfAxios.get(`/${userId}`); + } catch (error) { + assert.ok(error.message.startsWith('Invalid URL')); + return; + } + assert.fail('Expected an error to be thrown'); + }); + + describe('should fetch in client-side mode', () => { + let hasBrowserEnv, origin; + + before(() => { + hasBrowserEnv = utils.hasBrowserEnv; + origin = platform.origin; + utils.hasBrowserEnv = true; + platform.origin = 'http://localhost:' + String(GOOD_PORT); + }); + after(() => { + utils.hasBrowserEnv = hasBrowserEnv; + platform.origin = origin; + }); + it('should fetch in client-side mode', async () => { + utils.hasBrowserEnv = true; + const ssrfAxios = axios.create({ + baseURL: 'http://localhost:' + String(GOOD_PORT), + }); + + // Good payload would be `userId = '12345'` + // Malicious payload is as below. + const userId = '/localhost:' + String(BAD_PORT); + + const response = await ssrfAxios.get(`/${userId}`); + assert.strictEqual(response.data, 'bad'); + assert.strictEqual(response.config.baseURL, 'http://localhost:' + String(GOOD_PORT)); + assert.strictEqual(response.config.url, '//localhost:' + String(BAD_PORT)); + assert.strictEqual(response.request.res.responseUrl, 'http://localhost:' + String(BAD_PORT) + '/'); + }); }); });
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-8hc4-vh64-cxmjghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-39338ghsaADVISORY
- github.com/axios/axios/commit/6b6b605eaf73852fb2dae033f1e786155959de3aghsaWEB
- github.com/axios/axios/issues/6463ghsaWEB
- github.com/axios/axios/pull/6539ghsaWEB
- github.com/axios/axios/pull/6543ghsaWEB
- github.com/axios/axios/releases/tag/v1.7.4ghsaWEB
- jeffhacks.com/advisories/2024/06/24/CVE-2024-39338.htmlghsaWEB
News mentions
0No linked articles in our index yet.