CVE-2021-3647 (JavaScript, published 2021-07-16T11:15Z)
Description: value: URI.js is vulnerable to URL Redirection to Untrusted Site
Severity: MEDIUM (CVSS v3 base score: 6.1)
Weakness: CWE-601 \u2014 URL Redirection to Untrusted Site ('Open Redirect')
A web application accepts a user-controlled input that specifies a link to an external site, and uses that link in a Redirect. This simplifies phishing attacks.
Repository: https://github.com/medialize/URI.js
Files changed:
src/URI.js
test/urls.js
Commit message: fix(parse): more backslash galore #410

issue reported privately by @ready-research via https://huntr.dev/


Vulnerable code:

Fixed code:
    // slashes and backslashes have lost all meaning for the web protocols (https, http, wss, ws)
    string = string.replace(/^(https?|ftp|wss?)?:[/\\]*/, '$1://');

    }, {
      name: 'backslashes protocol excessive',
      url: 'https:/\/\/\attacker.com',
      _url: 'https://attacker.com/',
      parts: {
        protocol: 'https',
        username: null,
        password: null,
        hostname: 'attacker.com',
        port: null,
        path: '/',
        query: null,
        fragment: null
      },
      accessors: {
        protocol: 'https',
        username: '',
        password: '',
        port: '',
        path: '/',
        query: '',
        fragment: '',
        resource: '/',
        authority: 'attacker.com',
        origin: 'https://attacker.com',
        userinfo: '',
        subdomain: '',
        domain: 'attacker.com',
        tld: 'com',
        directory: '/',
        filename: '',
        suffix: '',
        hash: '',
        search: '',
        host: 'attacker.com',
        hostname: 'attacker.com'
      },
      is: {
        urn: false,
        url: true,
        relative: false,
        name: true,
        sld: false,
        ip: false,
        ip4: false,
        ip6: false,
        idn: false,
        punycode: false
      }
    }, {
      name: 'no slash protocol https',
      url: 'https:attacker.com',
      _url: 'https://attacker.com/',
      parts: {
        protocol: 'https',
        username: null,
        password: null,
        hostname: 'attacker.com',
        port: null,
        path: '/',
        query: null,
        fragment: null
      },
      accessors: {
        protocol: 'https',
        username: '',
        password: '',
        port: '',
        path: '/',
        query: '',
        fragment: '',
        resource: '/',
        authority: 'attacker.com',
        origin: 'https://attacker.com',
        userinfo: '',
        subdomain: '',
        domain: 'attacker.com',
        tld: 'com',
        directory: '/',
        filename: '',
        suffix: '',
        hash: '',
        search: '',
        host: 'attacker.com',
        hostname: 'attacker.com'
      },
      is: {
        urn: false,
        url: true,
        relative: false,
        name: true,
        sld: false,
        ip: false,
        ip4: false,
        ip6: false,
        idn: false,
        punycode: false
      }
    }, {
      name: 'single slash protocol https',
      url: 'https:/attacker.com',
      _url: 'https://attacker.com/',
      parts: {
        protocol: 'https',
        username: null,
        password: null,
        hostname: 'attacker.com',
        port: null,
        path: '/',
        query: null,
        fragment: null
      },
      accessors: {
        protocol: 'https',
        username: '',
        password: '',
        port: '',
        path: '/',
        query: '',
        fragment: '',
        resource: '/',
        authority: 'attacker.com',
        origin: 'https://attacker.com',
        userinfo: '',
        subdomain: '',
        domain: 'attacker.com',
        tld: 'com',
        directory: '/',
        filename: '',
        suffix: '',
        hash: '',
        search: '',
        host: 'attacker.com',
        hostname: 'attacker.com'
      },
      is: {
        urn: false,
        url: true,
        relative: false,
        name: true,
        sld: false,
        ip: false,
        ip4: false,
        ip6: false,
        idn: false,
        punycode: false
      }
    }, {
      name: 'excessive slash protocol https',
      url: 'https://////attacker.com',
      _url: 'https://attacker.com/',
      parts: {
        protocol: 'https',
        username: null,
        password: null,
        hostname: 'attacker.com',
        port: null,
        path: '/',
        query: null,
        fragment: null
      },
      accessors: {
        protocol: 'https',
        username: '',
        password: '',
        port: '',
        path: '/',
        query: '',
        fragment: '',
        resource: '/',
        authority: 'attacker.com',
        origin: 'https://attacker.com',
        userinfo: '',
        subdomain: '',
        domain: 'attacker.com',
        tld: 'com',
        directory: '/',
        filename: '',
        suffix: '',
        hash: '',
        search: '',
        host: 'attacker.com',
        hostname: 'attacker.com'
      },
      is: {
        urn: false,
        url: true,
        relative: false,
        name: true,
        sld: false,
        ip: false,
        ip4: false,
        ip6: false,
        idn: false,
        punycode: false
      }
    }, {
      name: 'no slash protocol ftp',
      url: 'ftp:attacker.com',
      _url: 'ftp://attacker.com/',
      parts: {
        protocol: 'ftp',
        username: null,
        password: null,
        hostname: 'attacker.com',
        port: null,
        path: '/',
        query: null,
        fragment: null
      },
      accessors: {
        protocol: 'ftp',
        username: '',
        password: '',
        port: '',
        path: '/',
        query: '',
        fragment: '',
        resource: '/',
        authority: 'attacker.com',
        origin: 'ftp://attacker.com',
        userinfo: '',
        subdomain: '',
        domain: 'attacker.com',
        tld: 'com',
        directory: '/',
        filename: '',
        suffix: '',
        hash: '',
        search: '',
        host: 'attacker.com',
        hostname: 'attacker.com'
      },
      is: {
        urn: false,
        url: true,
        relative: false,
        name: true,
        sld: false,
        ip: false,
        ip4: false,
        ip6: false,
        idn: false,
        punycode: false
      }
    }, {
      name: 'single slash protocol ftp',
      url: 'ftp:/attacker.com',
      _url: 'ftp://attacker.com/',
      parts: {
        protocol: 'ftp',
        username: null,
        password: null,
        hostname: 'attacker.com',
        port: null,
        path: '/',
        query: null,
        fragment: null
      },
      accessors: {
        protocol: 'ftp',
        username: '',
        password: '',
        port: '',
        path: '/',
        query: '',
        fragment: '',
        resource: '/',
        authority: 'attacker.com',
        origin: 'ftp://attacker.com',
        userinfo: '',
        subdomain: '',
        domain: 'attacker.com',
        tld: 'com',
        directory: '/',
        filename: '',
        suffix: '',
        hash: '',
        search: '',
        host: 'attacker.com',
        hostname: 'attacker.com'
      },
      is: {
        urn: false,
        url: true,
        relative: false,
        name: true,
        sld: false,
        ip: false,
        ip4: false,
        ip6: false,
        idn: false,
        punycode: false
      }
    }, {
      name: 'excessive slash protocol ftp',
      url: 'ftp://////attacker.com',
      _url: 'ftp://attacker.com/',
      parts: {
        protocol: 'ftp',
        username: null,
        password: null,
        hostname: 'attacker.com',
        port: null,
        path: '/',
        query: null,
        fragment: null
      },
      accessors: {
        protocol: 'ftp',
        username: '',
        password: '',
        port: '',
        path: '/',
        query: '',
        fragment: '',
        resource: '/',
        authority: 'attacker.com',
        origin: 'ftp://attacker.com',
        userinfo: '',
        subdomain: '',
        domain: 'attacker.com',
        tld: 'com',
        directory: '/',
        filename: '',
        suffix: '',
        hash: '',
        search: '',
        host: 'attacker.com',
        hostname: 'attacker.com'
      },
      is: {
        urn: false,
        url: true,
        relative: false,
        name: true,
        sld: false,
        ip: false,
        ip4: false,
        ip6: false,
        idn: false,
        punycode: false
      }