Skip to content

net/http: document that Request.SetBasicAuth doesn't do any additional escaping #31577

@tsuna

Description

@tsuna

What version of Go are you using (go version)?

$ go version
go version go1.12.4 darwin/amd64

Does this issue reproduce with the latest release?

Yes.

What did you do?

Call req.SetBasicAuth(user, pass) with special characters in either the username or the password, e.g.:

	req, err := http.NewRequest("POST", "http://127.0.0.1/foo", nil)
	req.SetBasicAuth("foo", "bar+baz")
	if err != nil {
		panic(err)
	}
	fmt.Println(req.Header.Get("Authorization"))

What did you expect to see?

The above program should probably print Basic Zm9vOmJhciUyQmJheg==

What did you see instead?

The above program prints Basic Zm9vOmJhcitiYXo=

Discussion

So I spent a long long long time debugging some OpenID Connect authentication issue with kubectl and dex. Long story short, it turns out that the random client secret I had generated contained a + sign and it needed to be URL encoded before being base64-encoded when used with basic auth.

After looking at the code in Kubernetes and various other projects, I realized that nobody ever escapes the arguments passed to SetBasicAuth(). So this issue is extremely widespread. In fact the bug was even present in Go's own OAuth2 implementation until golang/oauth2#237 fixed it.

The godoc doesn't say anything about escaping so it's not clear to me whether the intent was to have users do it themselves (and, clearly, they don't) or, more likely, this was just an unfortunate omission (i.e. a bug) when the library was implemented.

Given how widespread this issue is, I think the standard library should do the URL encoding automagically. Now since there are some callers that already do it (e.g. the OAuth2 library after the fix mentioned above), this means that the code should probably make a pass through the strings it's given and if they contain anything that needs escaping, then escape the whole string, otherwise use the string as-is.

If you guys disagree that the library should take care of escaping the arguments, then at the very least the godoc should be updated to explicitly state that the strings must be URL-safe or URL encoded. But I strongly think that the library should just make it work automatically given that virtually none of the existing code out there does this properly.

Granted this problem is probably not that likely to occur in practice, again I hit it because I used a random string of ASCII characters as a client secret, and there was a + in there. So kubectl worked for a while but once it needed to refresh its token, I'd get a mysterious 401 due to this bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocumentationIssues describing a change to documentation.FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions