net/http: validate trailers when writing requests and responses

When writing an HTTP/1 request or response, trailer names were copied
verbatim onto the "Trailer:" declaration line by writeHeader. The only
prior filtering was a switch rejecting the three reserved keys, and
CanonicalHeaderKey returns a key containing invalid bytes unchanged, so a
trailer name such as "X-Trailer\r\nInjected: 1" was written to the wire as
written, permitting header injection on the Trailer line.

Validate trailer names and values in newTransferWriter, which is the shared
HTTP/1 serialization path for Request.Write and Response.Write, before any
trailer is written. Names that fail httpguts.ValidHeaderFieldName and values
that fail httpguts.ValidHeaderFieldValue now cause the write to return an
error.

This path is distinct from Transport.roundTrip, which already validates
req.Trailer for client requests, and from the HTTP/2 and server
ResponseWriter trailer paths, which validate separately. The gap closed
here is the direct Request.Write / Response.Write serialization used by
callers such as httputil and code that writes a request to a connection
directly.

Rejecting invalid trailer values is stricter than the previous behavior, in
which the final trailer block sanitized CR and LF to spaces via
Header.writeSubset rather than erroring. Values whose final value is set
while the request body is read are still written through that sanitizing
path; the new check covers values present when the write begins.

Fixes #78775

Change-Id: I3ed66185ab262a215d0c8bbba005fd8b3df69acb
GitHub-Last-Rev: 9337c9d3f207fe8080e2dfd6b7f99971a7c56f33
GitHub-Pull-Request: golang/go#79971
Reviewed-on: https://go-review.googlesource.com/c/go/+/789960
Reviewed-by: Nicholas Husin <husin@google.com>
Auto-Submit: Emmanuel Odeke <emmanuel@orijtech.com>
Reviewed-by: Sayer Turner <sayerturner65@gmail.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Nicholas Husin <nsh@golang.org>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
4 files changed
tree: a708ccbce5cf4917bf65642788a1d1f6ff50913d
  1. .github/
  2. api/
  3. doc/
  4. lib/
  5. misc/
  6. src/
  7. test/
  8. .gitattributes
  9. .gitignore
  10. codereview.cfg
  11. CONTRIBUTING.md
  12. go.env
  13. LICENSE
  14. PATENTS
  15. README.md
  16. SECURITY.md
README.md

The Go Programming Language

Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.

Gopher image Gopher image by Renee French, licensed under Creative Commons 4.0 Attribution license.

Our canonical Git repository is located at https://go.googlesource.com/go. There is a mirror of the repository at https://github.com/golang/go.

Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file.

Download and Install

Binary Distributions

Official binary distributions are available at https://go.dev/dl/.

After downloading a binary release, visit https://go.dev/doc/install for installation instructions.

Install From Source

If a binary distribution is not available for your combination of operating system and architecture, visit https://go.dev/doc/install/source for source installation instructions.

Contributing

Go is the work of thousands of contributors. We appreciate your help!

To contribute, please read the contribution guidelines at https://go.dev/doc/contribute.

Note that the Go project uses the issue tracker for bug reports and proposals only. See https://go.dev/wiki/Questions for a list of places to ask questions about the Go language.