Blob Blame History Raw
From f06492430e8f4a37136c746a29cffb7149beae08 Mon Sep 17 00:00:00 2001
From: "brian m. carlson" <bk2204@github.com>
Date: Wed, 14 Aug 2019 14:49:48 +0000
Subject: [PATCH] lfsapi: fix URL parsing with Go 1.12.8

Go 1.12.8 introduces a security fix for parsing URLs that contain a
colon followed by an invalid port number. Since our SSH remotes can
contain just such a colon, our hack to make these into URLs no longer
works.

Fix this by replacing the first colon in these "URLs" with a slash,
which is a path delimiter, which makes them parsable by newer versions
of Go. Update the name of the function since it now does more than its
previous name implies.
---
 lfsapi/auth.go | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/lfsapi/auth.go b/lfsapi/auth.go
index 5a99a5b01..1de332e99 100644
--- a/lfsapi/auth.go
+++ b/lfsapi/auth.go
@@ -192,7 +192,7 @@ func getCredURLForAPI(ef EndpointFinder, operation, remote string, apiEndpoint l
 
 	if len(remote) > 0 {
 		if u := ef.GitRemoteURL(remote, operation == "upload"); u != "" {
-			schemedUrl, _ := prependEmptySchemeIfAbsent(u)
+			schemedUrl, _ := fixSchemelessURL(u)
 
 			gitRemoteURL, err := url.Parse(schemedUrl)
 			if err != nil {
@@ -214,12 +214,13 @@ func getCredURLForAPI(ef EndpointFinder, operation, remote string, apiEndpoint l
 	return apiURL, nil
 }
 
-// prependEmptySchemeIfAbsent prepends an empty scheme "//" if none was found in
-// the URL in order to satisfy RFC 3986 §3.3, and `net/url.Parse()`.
+// fixSchemelessURL prepends an empty scheme "//" if none was found in
+// the URL and replaces the first colon with a slash in order to satisfy RFC
+// 3986 §3.3, and `net/url.Parse()`.
 //
 // It returns a string parse-able with `net/url.Parse()` and a boolean whether
 // or not an empty scheme was added.
-func prependEmptySchemeIfAbsent(u string) (string, bool) {
+func fixSchemelessURL(u string) (string, bool) {
 	if hasScheme(u) {
 		return u, false
 	}
@@ -231,7 +232,11 @@ func prependEmptySchemeIfAbsent(u string) (string, bool) {
 		// First path segment has a colon, assumed that it's a
 		// scheme-less URL. Append an empty scheme on top to
 		// satisfy RFC 3986 §3.3, and `net/url.Parse()`.
-		return fmt.Sprintf("//%s", u), true
+		//
+		// In addition, replace the first colon with a slash since
+		// otherwise the colon looks like it's introducing a port
+		// number.
+		return fmt.Sprintf("//%s", strings.Replace(u, ":", "/", 1)), true
 	}
 	return u, true
 }