Skip to content

Commit ba1018b

Browse files
committed
net/url: reject invalid userinfo values when parsing URLs
Fixes #23392 Change-Id: I5822b082b14d886b9c3b5ad7beebb2c01a77851b Reviewed-on: https://go-review.googlesource.com/87038 Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent e858a6b commit ba1018b

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/net/url/url.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,9 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
563563
return nil, host, nil
564564
}
565565
userinfo := authority[:i]
566+
if !validUserinfo(userinfo) {
567+
return nil, "", errors.New("net/url: invalid userinfo")
568+
}
566569
if !strings.Contains(userinfo, ":") {
567570
if userinfo, err = unescape(userinfo, encodeUserPassword); err != nil {
568571
return nil, "", err
@@ -1069,3 +1072,33 @@ func (u *URL) UnmarshalBinary(text []byte) error {
10691072
*u = *u1
10701073
return nil
10711074
}
1075+
1076+
// validUserinfo reports whether s is a valid userinfo string per RFC 3986
1077+
// Section 3.2.1:
1078+
// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
1079+
// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
1080+
// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
1081+
// / "*" / "+" / "," / ";" / "="
1082+
//
1083+
// It doesn't validate pct-encoded. The caller does that via func unescape.
1084+
func validUserinfo(s string) bool {
1085+
for _, r := range s {
1086+
if 'A' <= r && r <= 'Z' {
1087+
continue
1088+
}
1089+
if 'a' <= r && r <= 'z' {
1090+
continue
1091+
}
1092+
if '0' <= r && r <= '9' {
1093+
continue
1094+
}
1095+
switch r {
1096+
case '-', '.', '_', ':', '~', '!', '$', '&', '\'',
1097+
'(', ')', '*', '+', ',', ';', '=', '%', '@':
1098+
continue
1099+
default:
1100+
return false
1101+
}
1102+
}
1103+
return true
1104+
}

src/net/url/url_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,3 +1735,10 @@ func TestNilUser(t *testing.T) {
17351735
t.Fatalf("expected empty string, got %s", v)
17361736
}
17371737
}
1738+
1739+
func TestInvalidUserPassword(t *testing.T) {
1740+
_, err := Parse("http://us\ner:pass\n[email protected]/")
1741+
if got, wantsub := fmt.Sprint(err), "net/url: invalid userinfo"; !strings.Contains(got, wantsub) {
1742+
t.Errorf("error = %q; want substring %q", got, wantsub)
1743+
}
1744+
}

0 commit comments

Comments
 (0)