Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions cli/connhelper/connhelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import (
"fmt"
"net"
"net/url"
"os"
"slices"
"strconv"
"strings"

"github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/connhelper/commandconn"
"github.com/docker/cli/cli/connhelper/ssh"
)
Expand Down Expand Up @@ -50,6 +53,7 @@ func getConnectionHelper(daemonURL string, sshFlags []string) (*ConnectionHelper
return nil, fmt.Errorf("ssh host connection is not valid: %w", err)
}
sshFlags = addSSHTimeout(sshFlags)
sshFlags = addMultiplexingArgs(sshFlags)
sshFlags = disablePseudoTerminalAllocation(sshFlags)

remoteCommand := []string{"docker", "system", "dial-stdio"}
Expand Down Expand Up @@ -83,6 +87,24 @@ func GetCommandConnectionHelper(cmd string, flags ...string) (*ConnectionHelper,
}, nil
}

func addMultiplexingArgs(sshFlags []string) []string {
if v := os.Getenv("DOCKER_SSH_NO_MUX"); v != "" {
if b, err := strconv.ParseBool(v); err == nil && b {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] DOCKER_SSH_NO_MUX=yes silently fails to disable multiplexing — only Go ParseBool strings accepted

strconv.ParseBool only recognises "1", "t", "T", "TRUE", "true", "True", "0", "f", "F", "FALSE", "false", "False". A user setting DOCKER_SSH_NO_MUX=yes (the common Unix/shell convention used by many tools) will have ParseBool return an error, making the condition err == nil && b false, and multiplexing will not be disabled — the env var is silently ignored.

The documentation in docker.md only says "If set will turn off SSH multiplexing" without clarifying which values are accepted, so users will be surprised.

Fix: Use the simpler v != "" check (consistent with how Docker treats DOCKER_TLS, NO_COLOR, etc.) or at minimum document the accepted values:

if v := os.Getenv("DOCKER_SSH_NO_MUX"); v != "" {
    return sshFlags
}

return sshFlags
}
}
if err := os.MkdirAll(config.Dir(), 0o700); err != nil {
return sshFlags
}
sshFlags = append(sshFlags, "-o", "ControlMaster=auto", "-o", "ControlPath="+config.Dir()+"/%r@%h:%p")
if v := os.Getenv("DOCKER_SSH_MUX_PERSIST"); v != "" {
sshFlags = append(sshFlags, "-o", "ControlPersist="+v)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] DOCKER_SSH_MUX_PERSIST value passed unsanitised into SSH -o ControlPersist option

The value of DOCKER_SSH_MUX_PERSIST is appended directly to the SSH flag string without any validation. While the SSH client receives it as a separate argv element (not a shell string, so no shell injection), there is no check that the value is a valid SSH duration (e.g. 60, 60s, yes, no). A malformed value (e.g. an empty suffix, a value with spaces) will be passed to the SSH client as-is and may result in confusing SSH errors rather than a clear user-facing message.

Suggestion: Validate the value against the expected format (integer seconds or SSH duration string) before appending, or at minimum document what values are accepted in the env var table.

} else {
sshFlags = append(sshFlags, "-o", "ControlPersist=60")
}
return sshFlags
}

func addSSHTimeout(sshFlags []string) []string {
if !strings.Contains(strings.Join(sshFlags, ""), "ConnectTimeout") {
sshFlags = append(sshFlags, "-o ConnectTimeout=30")
Expand Down
5 changes: 3 additions & 2 deletions docs/reference/commandline/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,12 @@ The following environment variables control the behavior of the `docker` command
| `DOCKER_DEFAULT_PLATFORM` | Default platform for commands that take the `--platform` flag. |
| `DOCKER_HIDE_LEGACY_COMMANDS` | When set, Docker hides "legacy" top-level commands (such as `docker rm`, and `docker pull`) in `docker help` output, and only `Management commands` per object-type (e.g., `docker container`) are printed. This may become the default in a future release. |
| `DOCKER_HOST` | Daemon socket to connect to. |
| `DOCKER_SSH_NO_MUX` | If set will turn off SSH multiplexing when connecting to daemon through SSH. |
| `DOCKER_SSH_MUX_PERSIST` | Set a duration for keeping SSH multiplexing socket alive between commands (e.g `60s`). |
| `DOCKER_TLS` | Enable TLS for connections made by the `docker` CLI (equivalent of the `--tls` command-line option). Set to a non-empty value to enable TLS. Note that TLS is enabled automatically if any of the other TLS options are set. |
| `DOCKER_TLS_VERIFY` | When set Docker uses TLS and verifies the remote. This variable is used both by the `docker` CLI and the [`dockerd` daemon](https://docs.docker.com/reference/cli/dockerd/) |
| `BUILDKIT_PROGRESS` | Set type of progress output (`auto`, `plain`, `tty`, `rawjson`) when [building](https://docs.docker.com/reference/cli/docker/image/build/) with [BuildKit backend](https://docs.docker.com/build/buildkit/). Use plain to show container output (default `auto`). |
| `NO_COLOR` | Disable any ANSI escape codes in the output in accordance with https://no-color.org/
|
| `NO_COLOR` | Disable any ANSI escape codes in the output in accordance with https://no-color.org/ |

Because Docker is developed using Go, you can also use any environment
variables used by the Go runtime. In particular, you may find these useful:
Expand Down
Loading