Ask questionsnet/http/cookie: readSetCookies does not strip whitespace for key/value pair received

<!-- Please answer these questions before submitting your issue. Thanks! For questions please use one of our forums: -->

What version of Go are you using (go version)?

<pre> $ go version go version go1.14.6 windows/amd64 </pre>

Does this issue reproduce with the latest release?

Yes. I'm using the latest go release for Windows.

What operating system and processor architecture are you using (go env)?

<details><summary><code>go env</code> Output</summary><br><pre> $ go env set GO111MODULE=on set GOARCH=amd64 set GOBIN= set GOCACHE=C:\Users-snip-\AppData\Local\go-build set GOENV=C:\Users-snip-\AppData\Roaming\go\env set GOEXE=.exe set GOFLAGS= set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOINSECURE= set GONOPROXY= set GONOSUMDB= set GOOS=windows set GOPATH=C:\Users-snip-\go set GOPRIVATE= set GOPROXY=,direct set GOROOT=C:\Go set set GOTMPDIR= set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64 set GCCGO=gccgo set AR=ar set CC=gcc set CXX=g++ set CGO_ENABLED=1 set GOMOD=-snip- set CGO_CFLAGS=-g -O2 set CGO_CPPFLAGS= set CGO_CXXFLAGS=-g -O2 set CGO_FFLAGS=-g -O2 set CGO_LDFLAGS=-g -O2 set PKG_CONFIG=pkg-config set GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users-snip-\AppData\Local\Temp\go-build817710326=/tmp/go-build -gno-record-gcc-switches </pre></details>

What did you do?

<!-- If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on is best. -->

Use http.Client with cookie jar to access site with valid Set-Cookie header, but the cookie did not persist.

The first two requests:

User-Agent: Go-http-client/1.1
Accept-Encoding: gzip

HTTP/1.1 200 OK
Date: Thu, 01 Jan 1970 00:00:00 GMT
Server: webserver
Connection: keep-alive
Keep-Alive: timeout=10, max=100
X-Download-Options: noopen
X-Frame-Options: deny
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000; includeSubdomains
Content-Length: 185
Content-Type: text/html
Expires: 0
Cache-Control: no-cache
Set-Cookie: SessionID=some_value;path =/;HttpOnly;

User-Agent: Go-http-client/1.1
Accept-Encoding: gzip

In the second request, the cookie did not persist. When looking at the cookie jar after the first request, the cookie has been stored under the path /html instead of expected /, which applies to the whole domain.

When I further examine the response header from the initial request, there's a white-space after the path key. This extra whitespace has caused readSetCookies to not recognise the key-pair, and the cookie has been stored relative to the document path (i.e. /html).

A quick read in RFC6265#5.2, step 4 states that the user-agent should strip leading or trailing whitespaces for the key/value string.

An attempt to fix this behaviour:

--- cookie.go   2020-07-16 22:30:44.000000000 +0100
+++ cookie_2.go 2020-07-26 11:33:31.710704300 +0100
@@ -92,8 +92,8 @@
                        if j := strings.Index(attr, "="); j >= 0 {
                                attr, val = attr[:j], attr[j+1:]
-                       lowerAttr := strings.ToLower(attr)
-                       val, ok = parseCookieValue(val, false)
+                       lowerAttr := strings.TrimSpace(strings.ToLower(attr))
+                       val, ok = parseCookieValue(strings.TrimSpace(val), false)
                        if !ok {
                                c.Unparsed = append(c.Unparsed, parts[i])

What did you expect to see?

The cookie is carried with subsequent requests.

What did you see instead?

The cookie was not set in subsequent requests, due to path mismatch.


Answer questions vdobler

/cc @nigeltao

This seems like a real bug. The "Note" in RFC 6265 5.2 makes it pretty clear:

NOTE: The algorithm below is more permissive than the grammar in Section 4.1. For example, the algorithm strips leading and trailing whitespace from the cookie name and value (but maintains internal whitespace), whereas the grammar in Section 4.1 forbids whitespace in these positions. User agents use this algorithm so as to interoperate with servers that do not follow the recommendations in Section 4.

So while sending a Set-Cookie header of the form Set-Cookie: SessionID=some_value;path =/;HttpOnly; is a violation of RFC 6265 we probably should accept it.

@jixunmoe You write

with valid Set-Cookie header The Set-Cookie header is technically not valid.


Related questions

cmd/link: segmentation fault during mach-o linking hot 6
cmd/vet: potential false positive in the "suspect or" check hot 4
cmd/go: cannot find module providing package error stops `go get` processing hot 3
vendor/ undefined: errors.Frame ... hot 2
cmd/cgo error: runtime: unknown pc 0x7fff5c805b86 hot 2
runtime: crash with "invalid pc-encoded table" hot 2
internal/poll: transparently support new linux io_uring interface hot 2
crypto/x509: 'certificate signed by unknown authority' on mipsle hot 2
x/tools/cmd/gopls: "build cache is required, but could not be located: GOCACHE is not defined and $HOME is not defined" hot 2
Plis fixit! Its not good!!! hot 2
cmd/go: needs a better error than "missing dot in first path element" when GOROOT is set incorrectly hot 2
encoding/json: invalid use of ,string struct tag, trying to unmarshal "" into int hot 2
Golang show warning after updating to 1.13 on OSX Catalina 10.15 hot 2
x/mobile: gomobile bind is failing with latest version [+cafc553] of gomobile hot 2
cmd/go: "found, but does not contain package" error refers to replaced version instead of its replacement hot 2
Github User Rank List