CVE-2022-0868: URL Redirection to Untrusted Site ('Open Redirect') (CWE-601)
value: Open Redirect in GitHub repository medialize/uri.js prior to 1.19.10.
CWE description: 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.
CVSS v3 base score: 6.1
Published: 2022-03-06T16:15Z
Repository: https://github.com/medialize/uri.js
Language: JavaScript
Files changed: src/URI.js, test/urls.js
Commit date: 2022-03-05 16:12:39 +0100
Commit message: fix(parse): handle excessive colons in scheme delimiter

reported by @huydoppa via huntr.dev

Diff: diff --git a/src/URI.js b/src/URI.js
index aeeed7e..610f6ce 100644
--- a/src/URI.js
+++ b/src/URI.js
@@ -515,11 +515,11 @@
       parts.query = string.substring(pos + 1) || null;
       string = string.substring(0, pos);
     }
 
     // slashes and backslashes have lost all meaning for the web protocols (https, http, wss, ws)
-    string = string.replace(/^(https?|ftp|wss?)?:[/\\]*/i, '$1://');
+    string = string.replace(/^(https?|ftp|wss?)?:+[/\\]*/i, '$1://');
 
     // extract protocol
     if (string.substring(0, 2) === '//') {
       // relative-scheme
       parts.protocol = null;
diff --git a/test/urls.js b/test/urls.js
index 4b077ce..ec6da7c 100644
--- a/test/urls.js
+++ b/test/urls.js
@@ -2618,8 +2618,106 @@ var urls = [{
         ip4: false,
         ip6: false,
         idn: false,
         punycode: false
       }
+    }, {
+      name: 'excessive colon in protocol delimiter',
+      url: 'http:://www.example.org:8080/hello:world',
+      _url: 'http://www.example.org:8080/hello:world',
+      parts: {
+        protocol: 'http',
+        username: null,
+        password: null,
+        hostname: 'www.example.org',
+        port: '8080',
+        path: '/hello:world',
+        query: null,
+        fragment: null
+      },
+      accessors: {
+        protocol: 'http',
+        username: '',
+        password: '',
+        port: '8080',
+        path: '/hello:world',
+        query: '',
+        fragment: '',
+        resource: '/hello:world',
+        authority: 'www.example.org:8080',
+        origin: 'http://www.example.org:8080',
+        userinfo: '',
+        subdomain: 'www',
+        domain: 'example.org',
+        tld: 'org',
+        directory: '/',
+        filename: 'hello:world',
+        suffix: '',
+        hash: '', // location.hash style
+        search: '', // location.search style
+        host: 'www.example.org:8080',
+        hostname: 'www.example.org'
+      },
+      is: {
+        urn: false,
+        url: true,
+        relative: false,
+        name: true,
+        sld: false,
+        ip: false,
+        ip4: false,
+        ip6: false,
+        idn: false,
+        punycode: false
+      }
+    }, {
+      name: 'excessive colon in protocol delimiter backslashes',
+      url: 'http::\\\\www.example.org:8080/hello:world',
+      _url: 'http://www.example.org:8080/hello:world',
+      parts: {
+        protocol: 'http',
+        username: null,
+        password: null,
+        hostname: 'www.example.org',
+        port: '8080',
+        path: '/hello:world',
+        query: null,
+        fragment: null
+      },
+      accessors: {
+        protocol: 'http',
+        username: '',
+        password: '',
+        port: '8080',
+        path: '/hello:world',
+        query: '',
+        fragment: '',
+        resource: '/hello:world',
+        authority: 'www.example.org:8080',
+        origin: 'http://www.example.org:8080',
+        userinfo: '',
+        subdomain: 'www',
+        domain: 'example.org',
+        tld: 'org',
+        directory: '/',
+        filename: 'hello:world',
+        suffix: '',
+        hash: '', // location.hash style
+        search: '', // location.search style
+        host: 'www.example.org:8080',
+        hostname: 'www.example.org'
+      },
+      is: {
+        urn: false,
+        url: true,
+        relative: false,
+        name: true,
+        sld: false,
+        ip: false,
+        ip4: false,
+        ip6: false,
+        idn: false,
+        punycode: false
+      }
     }
 ];
 

Vulnerable code:     string = string.replace(/^(https?|ftp|wss?)?:[/\\]*/i, '$1://');
Fixed code:     string = string.replace(/^(https?|ftp|wss?)?:+[/\\]*/i, '$1://');
    }, {
      name: 'excessive colon in protocol delimiter',
      url: 'http:://www.example.org:8080/hello:world',
      _url: 'http://www.example.org:8080/hello:world',
      parts: {
        protocol: 'http',
        username: null,
        password: null,
        hostname: 'www.example.org',
        port: '8080',
        path: '/hello:world',
        query: null,
        fragment: null
      },
      accessors: {
        protocol: 'http',
        username: '',
        password: '',
        port: '8080',
        path: '/hello:world',
        query: '',
        fragment: '',
        resource: '/hello:world',
        authority: 'www.example.org:8080',
        origin: 'http://www.example.org:8080',
        userinfo: '',
        subdomain: 'www',
        domain: 'example.org',
        tld: 'org',
        directory: '/',
        filename: 'hello:world',
        suffix: '',
        hash: '', // location.hash style
        search: '', // location.search style
        host: 'www.example.org:8080',
        hostname: 'www.example.org'
      },
      is: {
        urn: false,
        url: true,
        relative: false,
        name: true,
        sld: false,
        ip: false,
        ip4: false,
        ip6: false,
        idn: false,
        punycode: false
      }
    }, {
      name: 'excessive colon in protocol delimiter backslashes',
      url: 'http::\\\\www.example.org:8080/hello:world',
      _url: 'http://www.example.org:8080/hello:world',
      parts: {
        protocol: 'http',
        username: null,
        password: null,
        hostname: 'www.example.org',
        port: '8080',
        path: '/hello:world',
        query: null,
        fragment: null
      },
      accessors: {
        protocol: 'http',
        username: '',
        password: '',
        port: '8080',
        path: '/hello:world',
        query: '',
        fragment: '',
        resource: '/hello:world',
        authority: 'www.example.org:8080',
        origin: 'http://www.example.org:8080',
        userinfo: '',
        subdomain: 'www',
        domain: 'example.org',
        tld: 'org',
        directory: '/',
        filename: 'hello:world',
        suffix: '',
        hash: '', // location.hash style
        search: '', // location.search style
        host: 'www.example.org:8080',
        hostname: 'www.example.org'
      },
      is: {
        urn: false,
        url: true,
        relative: false,
        name: true,
        sld: false,
        ip: false,
        ip4: false,
        ip6: false,
        idn: false,
        punycode: false
      }