CVE-2015-5739 (Go, published 2017-10-18T20:29Z)
Description: value: The net/http library in net/textproto/reader.go in Go before 1.4.3 does not properly parse HTTP header keys, which allows remote attackers to conduct HTTP request smuggling attacks via a space instead of a hyphen, as demonstrated by "Content Length" instead of "Content-Length."
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-444 \u2014 Inconsistent Interpretation of HTTP Requests ('HTTP Request/Response Smuggling')
The product acts as an intermediary HTTP agent
         (such as a proxy or firewall) in the data flow between two
         entities such as a client and server, but it does not
         interpret malformed HTTP requests or responses in ways that
         are consistent with how the messages will be processed by
         those entities that are at the ultimate destination.
Repository: https://github.com/golang/go
Files changed:
src/net/http/header.go
src/net/textproto/reader.go
src/net/textproto/reader_test.go
Commit message: net/textproto: don't treat spaces as hyphens in header keys

This was originally done in https://codereview.appspot.com/5690059
(Feb 2012) to deal with bad response headers coming back from webcams,
but it presents a potential security problem with HTTP request
smuggling for request headers containing "Content Length" instead of
"Content-Length".

Part of overall HTTP hardening for request smuggling. See RFC 7230.

Thanks to Régis Leroy for the report.

Change-Id: I92b17fb637c9171c5774ea1437979ae2c17ca88a
Reviewed-on: https://go-review.googlesource.com/11772
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>


Vulnerable code:
		if c == ' ' {
			c = '-'
		} else if upper && 'a' <= c && c <= 'z' {
	{"üser-agenT", "üser-Agent"}, // non-ASCII unchanged
	{"C Ontent-Transfer-Encoding", "C-Ontent-Transfer-Encoding"},
	{"foo bar", "Foo-Bar"},
		"Audio-Mode":       {"None"},

Fixed code:
// If s contains a space or invalid header field bytes, it is
// returned without modifications.
// If s contains a space or invalid header field bytes, it is
// returned without modifications.
		if !validHeaderFieldByte(c) {
			return s
		}
// validHeaderFieldByte reports whether b is a valid byte in a header
// field key. This is actually stricter than RFC 7230, which says:
//   tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
//           "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
//   token = 1*tchar
// TODO: revisit in Go 1.6+ and possibly expand this. But note that many
// servers have historically dropped '_' to prevent ambiguities when mapping
// to CGI environment variables.
func validHeaderFieldByte(b byte) bool {
	return ('A' <= b && b <= 'Z') ||
		('a' <= b && b <= 'z') ||
		('0' <= b && b <= '9') ||
		b == '-'
}

//
// For invalid inputs (if a contains spaces or non-token bytes), a
// is unchanged and a string copy is returned.
	// See if a looks like a header key. If not, return it unchanged.
	for _, c := range a {
		if validHeaderFieldByte(c) {
			continue
		}
		// Don't canonicalize.
		return string(a)
	}

		if upper && 'a' <= c && c <= 'z' {

	// Non-ASCII or anything with spaces or non-token chars is unchanged:
	{"üser-agenT", "üser-agenT"},
	{"a B", "a B"},
	{"C Ontent-Transfer-Encoding", "C Ontent-Transfer-Encoding"},
	{"foo bar", "foo bar"},
		"Audio Mode":       {"None"},