VYPR
High severityNVD Advisory· Published Aug 9, 2024· Updated Aug 15, 2024

CVE-2024-39338

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.

PackageAffected versionsPatched versions
axiosnpm
>= 1.3.2, < 1.7.41.7.4

Affected products

62

Patches

2
6b6b605eaf73

fix(sec): CVE-2024-39338 (#6539) (#6543)

https://github.com/axios/axiosLev PachmanovAug 13, 2024via ghsa
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

News mentions

0

No linked articles in our index yet.