From: Damien Neil Date: Mon, 16 Aug 2021 17:46:06 +0000 (-0700) Subject: net/http: drop headers with invalid keys in Header.Write X-Git-Tag: go1.18beta1~1754 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=ec27168712;p=gostls13.git net/http: drop headers with invalid keys in Header.Write Don't let handlers inject unexpected headers by setting keys like: w.Header().Set("Evil: x\r\nSmuggle", y) Fixes #47711. Change-Id: I459ce1c79bc273a84230a0f5b665f81c46dbc672 Reviewed-on: https://go-review.googlesource.com/c/go/+/342530 Trust: Damien Neil Run-TryBot: Damien Neil Reviewed-by: Brad Fitzpatrick TryBot-Result: Go Bot --- diff --git a/src/net/http/header.go b/src/net/http/header.go index 4c72dcb2c8..cc9c28e3d0 100644 --- a/src/net/http/header.go +++ b/src/net/http/header.go @@ -13,6 +13,8 @@ import ( "strings" "sync" "time" + + "golang.org/x/net/http/httpguts" ) // A Header represents the key-value pairs in an HTTP header. @@ -192,6 +194,13 @@ func (h Header) writeSubset(w io.Writer, exclude map[string]bool, trace *httptra kvs, sorter := h.sortedKeyValues(exclude) var formattedVals []string for _, kv := range kvs { + if !httpguts.ValidHeaderFieldName(kv.key) { + // This could be an error. In the common case of + // writing reponse headers, however, we have no good + // way to provide the error back to the server + // handler, so just drop invalid headers instead. + continue + } for _, v := range kv.values { v = headerNewlineToSpace.Replace(v) v = textproto.TrimString(v) diff --git a/src/net/http/header_test.go b/src/net/http/header_test.go index 4789362919..57d16f51a5 100644 --- a/src/net/http/header_test.go +++ b/src/net/http/header_test.go @@ -89,6 +89,19 @@ var headerWriteTests = []struct { "k4: 4a\r\nk4: 4b\r\nk6: 6a\r\nk6: 6b\r\n" + "k7: 7a\r\nk7: 7b\r\nk8: 8a\r\nk8: 8b\r\nk9: 9a\r\nk9: 9b\r\n", }, + // Tests invalid characters in headers. + { + Header{ + "Content-Type": {"text/html; charset=UTF-8"}, + "NewlineInValue": {"1\r\nBar: 2"}, + "NewlineInKey\r\n": {"1"}, + "Colon:InKey": {"1"}, + "Evil: 1\r\nSmuggledValue": {"1"}, + }, + nil, + "Content-Type: text/html; charset=UTF-8\r\n" + + "NewlineInValue: 1 Bar: 2\r\n", + }, } func TestHeaderWrite(t *testing.T) {