aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Neil <dneil@google.com>2023-08-07 15:57:54 -0700
committerDamien Neil <dneil@google.com>2023-08-08 23:10:58 +0000
commit2d5ce9b729c0edded841301bd73d68d5e95aa28b (patch)
tree11d113ee1e8e538124cdea6b2953c8eff3bf5e12
parent6e43407931ee4acc204620a9fae59c7903164901 (diff)
downloadgo-2d5ce9b729c0edded841301bd73d68d5e95aa28b.tar.xz
net/http: sanitize User-Agent header in request writer
Apply the same transformations to the User-Agent header value that we do to other headers. Avoids header and request smuggling in Request.Write and Request.WriteProxy. RoundTrip already validates values in Request.Header, and didn't allow bad User-Agent values to make it as far as the request writer. Fixes #61824 Change-Id: I360a915c7e08d014e0532bd5af196a5b59c89395 Reviewed-on: https://go-review.googlesource.com/c/go/+/516836 Reviewed-by: Jonathan Amsterdam <jba@google.com> Run-TryBot: Damien Neil <dneil@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
-rw-r--r--src/net/http/request.go2
-rw-r--r--src/net/http/request_test.go19
2 files changed, 21 insertions, 0 deletions
diff --git a/src/net/http/request.go b/src/net/http/request.go
index d1fbd5df90..0fb73c12b5 100644
--- a/src/net/http/request.go
+++ b/src/net/http/request.go
@@ -669,6 +669,8 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF
userAgent = r.Header.Get("User-Agent")
}
if userAgent != "" {
+ userAgent = headerNewlineToSpace.Replace(userAgent)
+ userAgent = textproto.TrimString(userAgent)
_, err = fmt.Fprintf(w, "User-Agent: %s\r\n", userAgent)
if err != nil {
return err
diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
index a32b583c11..5711164894 100644
--- a/src/net/http/request_test.go
+++ b/src/net/http/request_test.go
@@ -787,6 +787,25 @@ func TestRequestBadHostHeader(t *testing.T) {
}
}
+func TestRequestBadUserAgent(t *testing.T) {
+ got := []string{}
+ req, err := NewRequest("GET", "http://foo/after", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ req.Header.Set("User-Agent", "evil\r\nX-Evil: evil")
+ req.Write(logWrites{t, &got})
+ want := []string{
+ "GET /after HTTP/1.1\r\n",
+ "Host: foo\r\n",
+ "User-Agent: evil X-Evil: evil\r\n",
+ "\r\n",
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Writes = %q\n Want = %q", got, want)
+ }
+}
+
func TestStarRequest(t *testing.T) {
req, err := ReadRequest(bufio.NewReader(strings.NewReader("M-SEARCH * HTTP/1.1\r\n\r\n")))
if err != nil {