From 73923af18638c8d61ee9f5de4f95a85689ee48f1 Mon Sep 17 00:00:00 2001 From: Steven Hilder Date: Thu, 30 Jan 2020 19:20:20 +0200 Subject: [PATCH 1/3] Ensure passwords in hosted Git URLs are correctly escaped --- index.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 2ccb1d69..b360c5f5 100644 --- a/index.js +++ b/index.js @@ -47,7 +47,7 @@ function fromUrl (giturl, opts) { var gitHostInfo = gitHosts[gitHostName] var auth = null if (parsed.auth && authProtocols[parsed.protocol]) { - auth = decodeURIComponent(parsed.auth) + auth = parsed.auth } var committish = parsed.hash ? decodeURIComponent(parsed.hash.substr(1)) : null var user = null @@ -106,7 +106,14 @@ function fixupUnqualifiedGist (giturl) { function parseGitUrl (giturl) { var matched = giturl.match(/^([^@]+)@([^:/]+):[/]?((?:[^/]+[/])?[^/]+?)(?:[.]git)?(#.*)?$/) - if (!matched) return url.parse(giturl) + if (!matched) { + var legacy = url.parse(giturl) + if (legacy.auth) { + var whatwg = new url.URL(giturl) + legacy.auth = whatwg.username + ':' + whatwg.password + } + return legacy + } return { protocol: 'git+ssh:', slashes: true, From 20edc2576773db5f397d9957baffa05913b5e688 Mon Sep 17 00:00:00 2001 From: Steven Hilder Date: Wed, 5 Feb 2020 12:00:15 +0200 Subject: [PATCH 2/3] Add test scenario for correct escaping of special characters in URL auth --- test/auth.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 test/auth.js diff --git a/test/auth.js b/test/auth.js new file mode 100644 index 00000000..41b601e8 --- /dev/null +++ b/test/auth.js @@ -0,0 +1,14 @@ +var HostedGitInfo = require('../') + +var tap = require('tap') +var url = require('url') + +// Auth credentials with special characters (colon and/or at-sign) should remain correctly escaped +var parsedInfo = HostedGitInfo.fromUrl('https://user%3An%40me:p%40ss%3Aword@github.com/npm/hosted-git-info.git') +tap.equal(parsedInfo.auth, 'user%3An%40me:p%40ss%3Aword') + +// Node.js' built-in `url` module should be able to parse the resulting url +var parsedUrl = new url.URL(parsedInfo.toString()) +tap.equal(parsedUrl.username, 'user%3An%40me') +tap.equal(parsedUrl.password, 'p%40ss%3Aword') +tap.equal(parsedUrl.hostname, 'github.com') From 702be08a2ac2e25144e00a7b7c1d8991477f73d3 Mon Sep 17 00:00:00 2001 From: Steven Hilder Date: Wed, 5 Feb 2020 13:01:40 +0200 Subject: [PATCH 3/3] Handle scenario where auth contains only username OR password, not both --- index.js | 3 ++- test/auth.js | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index b360c5f5..b94f6f1f 100644 --- a/index.js +++ b/index.js @@ -110,7 +110,8 @@ function parseGitUrl (giturl) { var legacy = url.parse(giturl) if (legacy.auth) { var whatwg = new url.URL(giturl) - legacy.auth = whatwg.username + ':' + whatwg.password + legacy.auth = whatwg.username || '' + if (whatwg.password) legacy.auth += ':' + whatwg.password } return legacy } diff --git a/test/auth.js b/test/auth.js index 41b601e8..0e5c752c 100644 --- a/test/auth.js +++ b/test/auth.js @@ -12,3 +12,7 @@ var parsedUrl = new url.URL(parsedInfo.toString()) tap.equal(parsedUrl.username, 'user%3An%40me') tap.equal(parsedUrl.password, 'p%40ss%3Aword') tap.equal(parsedUrl.hostname, 'github.com') + +// For full backwards-compatibility; support auth where only username or only password is provided +tap.equal(HostedGitInfo.fromUrl('https://user%3An%40me@github.com/npm/hosted-git-info.git').auth, 'user%3An%40me') +tap.equal(HostedGitInfo.fromUrl('https://:p%40ss%3Aword@github.com/npm/hosted-git-info.git').auth, ':p%40ss%3Aword')