Closed
Description
Go version
go version devel go1.23-b3acaa8230 Tue Jan 23 20:08:07 2024 +0000 linux/amd64
Output of go env
in your module/workspace:
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/root/.cache/go-build'
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/root/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/root/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/app/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/app/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='devel go1.23-b3acaa8230 Tue Jan 23 20:08:07 2024 +0000'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build965832195=/tmp/go-build -gno-record-gcc-switches'
What did you do?
Started a web server using net/http, and sent a request that contained a header with an empty name. (for example, GET / HTTP/1.1\r\n: ignored\r\nHost: whatever\r\n\r\n
)
What did you see happen?
The server ignored the offending header (It was not available through the Request.Header
interface)
What did you expect to see?
A 400 response. This is what Apache, Nginx, H2O, Node (with llhttp built from main), Lighttpd, and most other popular HTTP implementations do.
There are two reasons to reject messages with empty headers:
- The standard says that header names must be nonempty:
field-name = token token = 1*tchar tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA ; any VCHAR, except delimiters
- Some servers treat
\r\n:\r\n
as equivalent to\r\n\r\n
. Those servers will then see the end of the message body where net/http sees (and ignores) an empty header. This is a potential HTTP request smuggling vector.