|
| 1 | +From c85efebc0c9321fecc536485b47857dbcbe34ddf Mon Sep 17 00:00:00 2001 |
| 2 | +From: Sebastiaan van Stijn < [email protected]> |
| 3 | +Date: Wed, 12 Jul 2023 15:07:59 +0200 |
| 4 | +Subject: [PATCH 1/2] pkg/plugins: use a dummy hostname for local connections |
| 5 | + |
| 6 | +For local communications (npipe://, unix://), the hostname is not used, |
| 7 | +but we need valid and meaningful hostname. |
| 8 | + |
| 9 | +The current code used the socket path as hostname, which gets rejected by |
| 10 | +go1.20.6 and go1.19.11 because of a security fix for [CVE-2023-29406 ][1], |
| 11 | +which was implemented in https://go.dev/issue/60374. |
| 12 | + |
| 13 | +Prior versions go Go would clean the host header, and strip slashes in the |
| 14 | +process, but go1.20.6 and go1.19.11 no longer do, and reject the host |
| 15 | +header. |
| 16 | + |
| 17 | +Before this patch, tests would fail on go1.20.6: |
| 18 | + |
| 19 | + === FAIL: pkg/authorization TestAuthZRequestPlugin (15.01s) |
| 20 | + time="2023-07-12T12:53:45Z" level=warning msg="Unable to connect to plugin: //tmp/authz2422457390/authz-test-plugin.sock/AuthZPlugin.AuthZReq: Post \"http://%2F%2Ftmp%2Fauthz2422457390%2Fauthz-test-plugin.sock/AuthZPlugin.AuthZReq\": http: invalid Host header, retrying in 1s" |
| 21 | + time="2023-07-12T12:53:46Z" level=warning msg="Unable to connect to plugin: //tmp/authz2422457390/authz-test-plugin.sock/AuthZPlugin.AuthZReq: Post \"http://%2F%2Ftmp%2Fauthz2422457390%2Fauthz-test-plugin.sock/AuthZPlugin.AuthZReq\": http: invalid Host header, retrying in 2s" |
| 22 | + time="2023-07-12T12:53:48Z" level=warning msg="Unable to connect to plugin: //tmp/authz2422457390/authz-test-plugin.sock/AuthZPlugin.AuthZReq: Post \"http://%2F%2Ftmp%2Fauthz2422457390%2Fauthz-test-plugin.sock/AuthZPlugin.AuthZReq\": http: invalid Host header, retrying in 4s" |
| 23 | + time="2023-07-12T12:53:52Z" level=warning msg="Unable to connect to plugin: //tmp/authz2422457390/authz-test-plugin.sock/AuthZPlugin.AuthZReq: Post \"http://%2F%2Ftmp%2Fauthz2422457390%2Fauthz-test-plugin.sock/AuthZPlugin.AuthZReq\": http: invalid Host header, retrying in 8s" |
| 24 | + authz_unix_test.go:82: Failed to authorize request Post "http://%2F%2Ftmp%2Fauthz2422457390%2Fauthz-test-plugin.sock/AuthZPlugin.AuthZReq": http: invalid Host header |
| 25 | + |
| 26 | +[1]: https://github.com/advisories/GHSA-f8f7-69v5-w4vx |
| 27 | + |
| 28 | +Signed-off-by: Sebastiaan van Stijn < [email protected]> |
| 29 | + |
| 30 | +--- |
| 31 | + .../github.com/docker/docker/client/client.go | 30 +++++++++++++++++++ |
| 32 | + .../github.com/docker/docker/client/hijack.go | 6 +++- |
| 33 | + .../docker/docker/client/request.go | 10 +++---- |
| 34 | + 3 files changed, 39 insertions(+), 7 deletions(-) |
| 35 | + |
| 36 | +diff --git a/vendor/github.com/docker/docker/client/client.go b/vendor/github.com/docker/docker/client/client.go |
| 37 | +index 9b2b2eaeb8..5bf699d88d 100644 |
| 38 | +--- a/vendor/github.com/docker/docker/client/client.go |
| 39 | ++++ b/vendor/github.com/docker/docker/client/client.go |
| 40 | +@@ -57,6 +57,36 @@ import ( |
| 41 | + "github.com/pkg/errors" |
| 42 | + ) |
| 43 | + |
| 44 | ++// DummyHost is a hostname used for local communication. |
| 45 | ++// |
| 46 | ++// It acts as a valid formatted hostname for local connections (such as "unix://" |
| 47 | ++// or "npipe://") which do not require a hostname. It should never be resolved, |
| 48 | ++// but uses the special-purpose ".localhost" TLD (as defined in [RFC 2606, Section 2] |
| 49 | ++// and [RFC 6761, Section 6.3]). |
| 50 | ++// |
| 51 | ++// [RFC 7230, Section 5.4] defines that an empty header must be used for such |
| 52 | ++// cases: |
| 53 | ++// |
| 54 | ++// If the authority component is missing or undefined for the target URI, |
| 55 | ++// then a client MUST send a Host header field with an empty field-value. |
| 56 | ++// |
| 57 | ++// However, [Go stdlib] enforces the semantics of HTTP(S) over TCP, does not |
| 58 | ++// allow an empty header to be used, and requires req.URL.Scheme to be either |
| 59 | ++// "http" or "https". |
| 60 | ++// |
| 61 | ++// For further details, refer to: |
| 62 | ++// |
| 63 | ++// - https://github.com/docker/engine-api/issues/189 |
| 64 | ++// - https://github.com/golang/go/issues/13624 |
| 65 | ++// - https://github.com/golang/go/issues/61076 |
| 66 | ++// - https://github.com/moby/moby/issues/45935 |
| 67 | ++// |
| 68 | ++// [RFC 2606, Section 2]: https://www.rfc-editor.org/rfc/rfc2606.html#section-2 |
| 69 | ++// [RFC 6761, Section 6.3]: https://www.rfc-editor.org/rfc/rfc6761#section-6.3 |
| 70 | ++// [RFC 7230, Section 5.4]: https://datatracker.ietf.org/doc/html/rfc7230#section-5.4 |
| 71 | ++// [Go stdlib]: https://github.com/golang/go/blob/6244b1946bc2101b01955468f1be502dbadd6807/src/net/http/transport.go#L558-L569 |
| 72 | ++const DummyHost = "api.moby.localhost" |
| 73 | ++ |
| 74 | + // ErrRedirect is the error returned by checkRedirect when the request is non-GET. |
| 75 | + var ErrRedirect = errors.New("unexpected redirect in response") |
| 76 | + |
| 77 | +diff --git a/vendor/github.com/docker/docker/client/hijack.go b/vendor/github.com/docker/docker/client/hijack.go |
| 78 | +index e1dc49ef0f..b8fac0be7e 100644 |
| 79 | +--- a/vendor/github.com/docker/docker/client/hijack.go |
| 80 | ++++ b/vendor/github.com/docker/docker/client/hijack.go |
| 81 | +@@ -62,7 +62,11 @@ func fallbackDial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) { |
| 82 | + } |
| 83 | + |
| 84 | + func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto string) (net.Conn, error) { |
| 85 | +- req.Host = cli.addr |
| 86 | ++ req.URL.Host = cli.addr |
| 87 | ++ if cli.proto == "unix" || cli.proto == "npipe" { |
| 88 | ++ // Override host header for non-tcp connections. |
| 89 | ++ req.Host = DummyHost |
| 90 | ++ } |
| 91 | + req.Header.Set("Connection", "Upgrade") |
| 92 | + req.Header.Set("Upgrade", proto) |
| 93 | + |
| 94 | +diff --git a/vendor/github.com/docker/docker/client/request.go b/vendor/github.com/docker/docker/client/request.go |
| 95 | +index 7f54b1dd80..3fc99056d0 100644 |
| 96 | +--- a/vendor/github.com/docker/docker/client/request.go |
| 97 | ++++ b/vendor/github.com/docker/docker/client/request.go |
| 98 | +@@ -89,16 +89,14 @@ func (cli *Client) buildRequest(method, path string, body io.Reader, headers hea |
| 99 | + return nil, err |
| 100 | + } |
| 101 | + req = cli.addHeaders(req, headers) |
| 102 | ++ req.URL.Scheme = cli.scheme |
| 103 | ++ req.URL.Host = cli.addr |
| 104 | + |
| 105 | + if cli.proto == "unix" || cli.proto == "npipe" { |
| 106 | +- // For local communications, it doesn't matter what the host is. We just |
| 107 | +- // need a valid and meaningful host name. (See #189) |
| 108 | +- req.Host = "docker" |
| 109 | ++ // Override host header for non-tcp connections. |
| 110 | ++ req.Host = DummyHost |
| 111 | + } |
| 112 | + |
| 113 | +- req.URL.Host = cli.addr |
| 114 | +- req.URL.Scheme = cli.scheme |
| 115 | +- |
| 116 | + if expectedPayload && req.Header.Get("Content-Type") == "" { |
| 117 | + req.Header.Set("Content-Type", "text/plain") |
| 118 | + } |
| 119 | +-- |
| 120 | +2.34.1 |
| 121 | + |
0 commit comments