CVE-2022-0512 (JavaScript, published 2022-02-14T16:15Z)
Description: value: Authorization Bypass Through User-Controlled Key in NPM url-parse prior to 1.5.6.
Severity: MEDIUM (CVSS v3 base score: 5.3)
Weakness: CWE-639 \u2014 Authorization Bypass Through User-Controlled Key
The system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data.
Repository: https://github.com/unshiftio/url-parse
Files changed:
index.js
test/test.js
Commit message: [fix] Correctly handle userinfo containing the at sign


Vulnerable code:
      if (~(index = address.indexOf(parse))) {
    instruction = url.auth.split(':');
    url.username = instruction[0];
    url.password = instruction[1] || '';
      var splits = value.split(':');
      url.username = splits[0];
      url.password = splits.length === 2 ? splits[1] : '';

Fixed code:
      index = parse === '@'
        ? address.lastIndexOf(parse)
        : address.indexOf(parse);

      if (~index) {

    index = url.auth.indexOf(':');

    if (~index) {
      url.username = url.auth.slice(0, index);
      url.username = encodeURIComponent(decodeURIComponent(url.username));

      url.password = url.auth.slice(index + 1);
      url.password = encodeURIComponent(decodeURIComponent(url.password))
    } else {
      url.username = encodeURIComponent(decodeURIComponent(url.auth));
    }

    url.auth = url.password ? url.username +':'+ url.password : url.username;
      var index = value.indexOf(':');

      if (~index) {
        url.username = value.slice(0, index);
        url.username = encodeURIComponent(decodeURIComponent(url.username));

        url.password = value.slice(index + 1);
        url.password = encodeURIComponent(decodeURIComponent(url.password));
      } else {
        url.username = encodeURIComponent(decodeURIComponent(value));
      }

    it('handles @ in username', function () {
      var url = 'http://user@@www.example.com/'
        , parsed = parse(url);

      assume(parsed.protocol).equals('http:');
      assume(parsed.auth).equals('user%40');
      assume(parsed.username).equals('user%40');
      assume(parsed.password).equals('');
      assume(parsed.hostname).equals('www.example.com');
      assume(parsed.pathname).equals('/');
      assume(parsed.href).equals('http://user%40@www.example.com/');

      url = 'http://user%40@www.example.com/';
      parsed = parse(url);

      assume(parsed.protocol).equals('http:');
      assume(parsed.auth).equals('user%40');
      assume(parsed.username).equals('user%40');
      assume(parsed.password).equals('');
      assume(parsed.hostname).equals('www.example.com');
      assume(parsed.pathname).equals('/');
      assume(parsed.href).equals('http://user%40@www.example.com/');
    });

    it('handles @ in password', function () {
      var url = 'http://user@:pas:s@@www.example.com/'
        , parsed = parse(url);

      assume(parsed.protocol).equals('http:');
      assume(parsed.auth).equals('user%40:pas%3As%40');
      assume(parsed.username).equals('user%40');
      assume(parsed.password).equals('pas%3As%40');
      assume(parsed.hostname).equals('www.example.com');
      assume(parsed.pathname).equals('/');
      assume(parsed.href).equals('http://user%40:pas%3As%40@www.example.com/');

      url = 'http://user%40:pas%3As%40@www.example.com/'
      parsed = parse(url);

      assume(parsed.protocol).equals('http:');
      assume(parsed.auth).equals('user%40:pas%3As%40');
      assume(parsed.username).equals('user%40');
      assume(parsed.password).equals('pas%3As%40');
      assume(parsed.hostname).equals('www.example.com');
      assume(parsed.pathname).equals('/');
      assume(parsed.href).equals('http://user%40:pas%3As%40@www.example.com/');
    });

      assume(data.set('auth', 'user@:pass@')).equals(data);
      assume(data.username).equals('user%40');
      assume(data.password).equals('pass%40');
      assume(data.href).equals('https://user%40:pass%40@example.com/');

      assume(data.set('auth', 'user%40:pass%40')).equals(data);
      assume(data.username).equals('user%40');
      assume(data.password).equals('pass%40');
      assume(data.href).equals('https://user%40:pass%40@example.com/');

      assume(data.set('auth', 'user:pass:word')).equals(data);
      assume(data.username).equals('user');
      assume(data.password).equals('pass%3Aword');
      assume(data.href).equals('https://user:pass%3Aword@example.com/');

      assume(data.set('auth', 'user:pass%3Aword')).equals(data);
      assume(data.username).equals('user');
      assume(data.password).equals('pass%3Aword');
      assume(data.href).equals('https://user:pass%3Aword@example.com/');