From 01ee7000fc7ed36bad18c9a79a75967d54933286 Mon Sep 17 00:00:00 2001 From: isaacs Date: Wed, 26 Feb 2020 14:20:02 -0800 Subject: [PATCH] fix: Do not pass scp-style URLs to the WhatWG url.URL Fix #60 --- index.js | 19 ++++++++++++++++--- package.json | 2 +- test/basic.js | 2 ++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index b94f6f1..0b08be1 100644 --- a/index.js +++ b/index.js @@ -109,9 +109,22 @@ function parseGitUrl (giturl) { if (!matched) { var legacy = url.parse(giturl) if (legacy.auth) { - var whatwg = new url.URL(giturl) - legacy.auth = whatwg.username || '' - if (whatwg.password) legacy.auth += ':' + whatwg.password + // git urls can be in the form of scp-style/ssh-connect strings, like + // git+ssh://user@host.com:some/path, which the legacy url parser + // supports, but WhatWG url.URL class does not. However, the legacy + // parser de-urlencodes the username and password, so something like + // https://user%3An%40me:p%40ss%3Aword@x.com/ becomes + // https://user:n@me:p@ss:word@x.com/ which is all kinds of wrong. + // Pull off just the auth and host, so we dont' get the confusing + // scp-style URL, then pass that to the WhatWG parser to get the + // auth properly escaped. + const authmatch = giturl.match(/[^@]+@[^:/]+/) + /* istanbul ignore else - this should be impossible */ + if (authmatch) { + var whatwg = new url.URL(authmatch[0]) + legacy.auth = whatwg.username || '' + if (whatwg.password) legacy.auth += ':' + whatwg.password + } } return legacy } diff --git a/package.json b/package.json index 0f0faf0..4e82801 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "scripts": { "prerelease": "npm t", "postrelease": "npm publish && git push --follow-tags", - "pretest": "standard", + "posttest": "standard", "release": "standard-version -s", "test:coverage": "tap --coverage-report=html -J --100 --no-esm test/*.js", "test": "tap -J --100 --no-esm test/*.js" diff --git a/test/basic.js b/test/basic.js index 76a8d6f..e41b637 100644 --- a/test/basic.js +++ b/test/basic.js @@ -37,6 +37,8 @@ test('basic', function (t) { t.is(HostedGit.fromUrl('github.com/abc/def/'), undefined, 'forgot the protocol') t.is(HostedGit.fromUrl('completely-invalid'), undefined, 'not a url is not hosted') + t.is(HostedGit.fromUrl('git+ssh://git@git.unlucky.com:RND/electron-tools/some-tool#2.0.1'), undefined, 'properly ignores non-hosted scp style urls') + t.is(HostedGit.fromUrl('http://github.com/foo/bar').toString(), 'git+ssh://git@github.com/foo/bar.git', 'github http protocol use git+ssh urls') t.end() })