Closed
Description
Consider the following code:
import (
"fmt"
"net/http"
)
func main() {
req, err := http.NewRequest("GET", "https://example.com", nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "secret")
fmt.Println(req)
}
// Prints
// &{GET https://example.com HTTP/1.1 %!s(int=1) %!s(int=1) map[Authorization:[secret]] <nil> %!s(func() (io.ReadCloser, error)=<nil>) %!s(int64=0) [] %!s(bool=false) example.com map[] map[] %!s(*multipart.Form=<nil>) map[] %!s(*tls.ConnectionState=<nil>) %!s(<-chan struct {}=<nil>) %!s(*http.Response=<nil>) <nil>}
This type of code is fairly common, but can lead to exposing the Authorization
header (or Cookie
). Instead we should opt to not expose these sensitive headers by default. There's similar precedent for masking userinfo passwords from urls in #24572.
We need to keep req.Header.Get("Authorization")
unchanged as servers read the auth blob that way. Instead I propose we add:
func (h Header) String() string
As part of the implementation we might need to specify a format for headers. Looking through various Printf encodings gives us:
verb | output |
---|---|
%s |
map[Authorization:[secret]] |
%#v |
Header:http.Header{"Authorization":[]string{"secret"}} |
%+v |
Header:map[Authorization:[secret]] |
With a fixed encoding we are able to write the formatter and always mask these sensitive headers.