-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net/http: go 1.20.6 host validation breaks setting Host to a unix socket address #61431
Comments
CC @neild @golang/security |
Not entirely sure how common this behavior is, but I will note that RFC 2616 Section 14.23 does seem to explicitly disallow this:
|
This looks like misusing the Aside: the file transport from |
I feel that discussing if this is allowed or not is not the most important aspect. As it worked before, it created an API and created expectations (see relevant xkcd). The fallout it created relates to a lot of docker-based technologies which make heavy use of sockets. Examples I could find/affect me are: k3d-io/k3d#1321 As a lot of people are scrambling to fix the fallout, I think the good outcome will be a better understanding of potential downstream issues of „overcorrections“ and a better understanding of the standards in any case. |
Per #56986, the new validation should probably at least have a |
It sounds like given the scope of those relying on this behavior we'll need to at least partial revert this. I'd like to keep the extremely strict behavior, at least behind a GODEBUG, so that we can work on pushing the ecosystem away from relying on this. It seems like the main offender here is Docker? |
I would say any client connecting to an HTTP server over a unix socket. |
I don't think we need a GODEBUG; we can reduce the validation of outgoing Host headers to just checking that it's a valid header value, not that it's a valid Host header specifically. That's enough to ensure the outbound request is, at worst, something the server will reject. |
Change https://go.dev/cl/511155 mentions this issue: |
Ugh, it's worse than I thought. Our previous behavior was to silently truncate Host headers in HTTP/1 requests at the first I suspect Docker is relying on that silent truncation, since otherwise the invalid So I think the thing to do is reduce the validation to just checking that we're sending a valid header value (which is the minimum required) and restore the old truncation behavior. Perhaps we should have a GODEBUG for the truncation, although unless we have a plan for how to change it in the future that's probably just useless complexity. |
Change https://go.dev/cl/511156 mentions this issue: |
Any chance something was backported to go1.19.11 linux/amd64 too? We started seeing a similar behavior there on GitHub actions: wiremock/wiremock-testcontainers-go#18 |
@oleg-nenashev, yes, this change was backported to Go 1.19.11 as well. (See #61075.) |
@bcmills Yes, I confirm the regression: wiremock/wiremock-testcontainers-go#19 P.S: Probably wasn't the greatest time to release the new WireMock module for Testcontainers Go :) Will add to Errata while we we wait for a fix/revert on one of the sides |
I suggest that:
(The “Go 1.22 and above” part can be implemented by adding an entry to |
That's my thought as well. |
Pin Go to version `1.20.5` to fix [testcontainer](https://golang.testcontainers.org/) tests. Go `1.20.6` introduced changes in `Host` header parsing ([issue](golang/go#61431)) which breaks `testcontainers-go` ([issue](testcontainers/testcontainers-go#1359)). Our tests started failing consistently yesterday due to this issue ([example run](https://github.com/xataio/pg-roll/actions/runs/5612153506)). The suggested workaround until this is resolved upstream is to pin to `1.20.5`.
@mholt Not quite sure I'm following your comment about CORS, since the Host header plays no part in the CORS protocol. |
DNS rebinding mitigation does, which is also important; but all the same, we need a host (even if it's used in the Origin header), if we cannot leave it blank. |
Starting from Go 1.20.6 (net/http: go 1.20.6 host validation breaks setting Host to a unix socket address golang/go#61431) calling unix socket address no longer allows Host to be empty, Allow loopback hosts for admin endpoint from (caddyserver/caddy#5664)
https://go.dev/cl/511155 changes the transport to send an empty Host header when the host is invalid, except in the case of a request sent to a proxy. Returning an error seems more useful than sending a destination-free request to a proxy. Sending an empty Host offers less potential for request smuggling than truncating at the first invalid character. Are there any scenarios that I'm missing that this won't cover? |
@gopherbot please open backport issues. This is a regression. |
Backport issue(s) opened: #61825 (for 1.19), #61826 (for 1.20). Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases. |
Change https://go.dev/cl/518855 mentions this issue: |
Change https://go.dev/cl/518756 mentions this issue: |
Change https://go.dev/cl/518856 mentions this issue: |
* Adding support for pod auth * Bumped dependencies and exposed more pod auth fields * Tests now pass * Fix for bug golang/go#61431 * Checking the cluster certificate path * Updated the dependencies
…eaders Historically, the Transport has silently truncated invalid Host headers at the first '/' or ' ' character. CL 506996 changed this behavior to reject invalid Host headers entirely. Unfortunately, Docker appears to rely on the previous behavior. When sending a HTTP/1 request with an invalid Host, send an empty Host header. This is safer than truncation: If you care about the Host, then you should get the one you set; if you don't care, then an empty Host should be fine. Continue to fully validate Host headers sent to a proxy, since proxies generally can't productively forward requests without a Host. For #60374 Fixes #61431 Fixes #61904 Change-Id: If170c7dd860aa20eb58fe32990fc93af832742b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/511155 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Roland Shoemaker <roland@golang.org> Run-TryBot: Damien Neil <dneil@google.com> (cherry picked from commit b9153f6) Reviewed-on: https://go-review.googlesource.com/c/go/+/518856 Auto-Submit: Dmitri Shuralyov <dmitshur@google.com> Run-TryBot: Roland Shoemaker <roland@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
…eaders Historically, the Transport has silently truncated invalid Host headers at the first '/' or ' ' character. CL 506996 changed this behavior to reject invalid Host headers entirely. Unfortunately, Docker appears to rely on the previous behavior. When sending a HTTP/1 request with an invalid Host, send an empty Host header. This is safer than truncation: If you care about the Host, then you should get the one you set; if you don't care, then an empty Host should be fine. Continue to fully validate Host headers sent to a proxy, since proxies generally can't productively forward requests without a Host. For #60374 Fixes #61431 Fixes #61826 Change-Id: If170c7dd860aa20eb58fe32990fc93af832742b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/511155 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Roland Shoemaker <roland@golang.org> Run-TryBot: Damien Neil <dneil@google.com> (cherry picked from commit b9153f6) Reviewed-on: https://go-review.googlesource.com/c/go/+/518756 Auto-Submit: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Roland Shoemaker <roland@golang.org>
…eaders Historically, the Transport has silently truncated invalid Host headers at the first '/' or ' ' character. CL 506996 changed this behavior to reject invalid Host headers entirely. Unfortunately, Docker appears to rely on the previous behavior. When sending a HTTP/1 request with an invalid Host, send an empty Host header. This is safer than truncation: If you care about the Host, then you should get the one you set; if you don't care, then an empty Host should be fine. Continue to fully validate Host headers sent to a proxy, since proxies generally can't productively forward requests without a Host. For #60374 Fixes #61431 Fixes #61825 Change-Id: If170c7dd860aa20eb58fe32990fc93af832742b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/511155 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Roland Shoemaker <roland@golang.org> Run-TryBot: Damien Neil <dneil@google.com> (cherry picked from commit b9153f6) Reviewed-on: https://go-review.googlesource.com/c/go/+/518855 Auto-Submit: Dmitri Shuralyov <dmitshur@google.com> Run-TryBot: Roland Shoemaker <roland@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?can include this if requested
What did you do?
Create a request where the Host header is a unix socket address. Here's some runnable sample code:
What did you expect to see?
In Go 1.20.5, this prints:
What did you see instead?
In Go 1.20.6, this prints:
Additional Info
Related discussion: #60374
My understanding is that this is an intentional change, to fix a security bug where the Host header contains newline characters. Here's the CVE: https://nvd.nist.gov/vuln/detail/CVE-2023-29406
Unforuntately, this also breaks CLIs in the Go ecosystem that set the Host header to a unix socket, for example : moby/moby#45935
Many projects silently upgrade from Go 1.20.5 -> 1.20.6, so we're starting to see this change break tons of projects in the go ecosystem.
My humble request is that the security fix on the Go 1.20 release branch could be more narrowly targeted at the security issue, and allow this Host header format, to unbreak the ecosystem. The Go 1.21 release line can more safely rollout the backwards-incompatible part of the change.
The text was updated successfully, but these errors were encountered: