diff --git a/cli/command/stack/loader/loader.go b/cli/command/stack/loader/loader.go index 105e84e644..8b5359dd95 100644 --- a/cli/command/stack/loader/loader.go +++ b/cli/command/stack/loader/loader.go @@ -5,6 +5,7 @@ import ( "io" "os" "path/filepath" + "runtime" "sort" "strings" @@ -104,6 +105,19 @@ func GetConfigDetails(composefiles []string, stdin io.Reader) (composetypes.Conf func buildEnvironment(env []string) (map[string]string, error) { result := make(map[string]string, len(env)) for _, s := range env { + if runtime.GOOS == "windows" && len(s) > 0 { + // cmd.exe can have special environment variables which names start with "=". + // They are only there for MS-DOS compatibility and we should ignore them. + // See TestBuildEnvironment for examples. + // + // https://ss64.com/nt/syntax-variables.html + // https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133 + // https://github.com/docker/cli/issues/4078 + if s[0] == '=' { + continue + } + } + k, v, ok := strings.Cut(s, "=") if !ok || k == "" { return result, errors.Errorf("unexpected environment %q", s) diff --git a/cli/command/stack/loader/loader_test.go b/cli/command/stack/loader/loader_test.go index 6ddca65bb8..6c0da17aa3 100644 --- a/cli/command/stack/loader/loader_test.go +++ b/cli/command/stack/loader/loader_test.go @@ -3,6 +3,7 @@ package loader import ( "os" "path/filepath" + "runtime" "strings" "testing" @@ -45,3 +46,34 @@ services: assert.Check(t, is.Equal("3.0", details.ConfigFiles[0].Config["version"])) assert.Check(t, is.Len(details.Environment, len(os.Environ()))) } + +func TestBuildEnvironment(t *testing.T) { + inputEnv := []string{ + "LEGIT_VAR=LEGIT_VALUE", + "EMPTY_VARIABLE=", + } + + if runtime.GOOS == "windows" { + inputEnv = []string{ + "LEGIT_VAR=LEGIT_VALUE", + + // cmd.exe has some special environment variables which start with "=". + // These should be ignored as they're only there for MS-DOS compatibility. + "=ExitCode=00000041", + "=ExitCodeAscii=A", + `=C:=C:\some\dir`, + `=D:=D:\some\different\dir`, + `=X:=X:\`, + `=::=::\`, + + "EMPTY_VARIABLE=", + } + } + + env, err := buildEnvironment(inputEnv) + assert.NilError(t, err) + + assert.Check(t, is.Len(env, 2)) + assert.Check(t, is.Equal("LEGIT_VALUE", env["LEGIT_VAR"])) + assert.Check(t, is.Equal("", env["EMPTY_VARIABLE"])) +}