From 5bd98a810b577ddba728e836db97254cff3a504d Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Tue, 17 Mar 2026 22:47:10 -0700 Subject: [PATCH] fix: unquote environment variable passed to hook commands --- internal/hooks/hook_executor_default_test.go | 8 ++++---- internal/hooks/hook_executor_v2_test.go | 12 ++++++------ internal/hooks/hooks.go | 4 +++- internal/pkg/platform/localserver.go | 5 +++-- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/internal/hooks/hook_executor_default_test.go b/internal/hooks/hook_executor_default_test.go index dba9cf9a..6c343a70 100644 --- a/internal/hooks/hook_executor_default_test.go +++ b/internal/hooks/hook_executor_default_test.go @@ -60,8 +60,8 @@ func Test_Hook_Execute_Default_Protocol(t *testing.T) { opts: HookExecOpts{ Hook: HookScript{Name: "happypath", Command: "echo {}"}, Env: map[string]string{ - "batman": "robin", - "yin": "yang", + "BATMAN": "robin hood", + "YIN": "yang", }, Exec: &MockExec{ mockCommand: &MockCommand{ @@ -74,8 +74,8 @@ func Test_Hook_Execute_Default_Protocol(t *testing.T) { response, err := executor.Execute(ctx, opts) require.Equal(t, "test output", response) require.Equal(t, nil, err) - require.Contains(t, opts.Exec.(*MockExec).mockCommand.Env, `batman="robin"`) - require.Contains(t, opts.Exec.(*MockExec).mockCommand.Env, `yin="yang"`) + require.Contains(t, opts.Exec.(*MockExec).mockCommand.Env, `BATMAN=robin hood`) + require.Contains(t, opts.Exec.(*MockExec).mockCommand.Env, `YIN=yang`) }, }, "failed execution": { diff --git a/internal/hooks/hook_executor_v2_test.go b/internal/hooks/hook_executor_v2_test.go index ee44088a..bd1c21a7 100644 --- a/internal/hooks/hook_executor_v2_test.go +++ b/internal/hooks/hook_executor_v2_test.go @@ -55,8 +55,8 @@ func Test_Hook_Execute_V2_Protocol(t *testing.T) { opts: HookExecOpts{ Hook: HookScript{Name: "happypath", Command: "echo {}"}, Env: map[string]string{ - "batman": "robin", - "yin": "yang", + "BATMAN": "robin hood", + "YIN": "yang", }, Exec: &MockExec{ mockCommand: &MockCommand{ @@ -68,8 +68,8 @@ func Test_Hook_Execute_V2_Protocol(t *testing.T) { check: func(t *testing.T, response string, err error, mockExec ExecInterface) { require.Equal(t, `{"message": "hello world"}`, response) require.Equal(t, nil, err) - require.Contains(t, mockExec.(*MockExec).mockCommand.Env, `batman="robin"`) - require.Contains(t, mockExec.(*MockExec).mockCommand.Env, `yin="yang"`) + require.Contains(t, mockExec.(*MockExec).mockCommand.Env, `BATMAN=robin hood`) + require.Contains(t, mockExec.(*MockExec).mockCommand.Env, `YIN=yang`) }, }, "successful execution with payload > 64kb": { @@ -89,8 +89,8 @@ func Test_Hook_Execute_V2_Protocol(t *testing.T) { check: func(t *testing.T, response string, err error, mockExec ExecInterface) { require.Equal(t, sixtyFourKBString, response) require.Equal(t, nil, err) - require.Contains(t, mockExec.(*MockExec).mockCommand.Env, `batman="robin"`) - require.Contains(t, mockExec.(*MockExec).mockCommand.Env, `yin="yang"`) + require.Contains(t, mockExec.(*MockExec).mockCommand.Env, `batman=robin`) + require.Contains(t, mockExec.(*MockExec).mockCommand.Env, `yin=yang`) }, }, "successful execution with payload > 512kb": { diff --git a/internal/hooks/hooks.go b/internal/hooks/hooks.go index dcf3a33a..49ebf8a6 100644 --- a/internal/hooks/hooks.go +++ b/internal/hooks/hooks.go @@ -57,7 +57,9 @@ func processExecOpts(opts HookExecOpts) ([]string, []string, []string, error) { // To avoid removing any environment variables that are set in the current environment, we first set the cmd.Env to the current environment. // before adding any new environment variables. var cmdEnvVars = os.Environ() - cmdEnvVars = append(cmdEnvVars, goutils.MapToStringSlice(opts.Env, "")...) + for name, value := range opts.Env { + cmdEnvVars = append(cmdEnvVars, name+"="+value) + } return cmdArgs, cmdArgVars, cmdEnvVars, nil } diff --git a/internal/pkg/platform/localserver.go b/internal/pkg/platform/localserver.go index ed1735bc..28b87041 100644 --- a/internal/pkg/platform/localserver.go +++ b/internal/pkg/platform/localserver.go @@ -30,7 +30,6 @@ import ( "github.com/gorilla/websocket" "github.com/radovskyb/watcher" "github.com/slackapi/slack-cli/internal/config" - "github.com/slackapi/slack-cli/internal/goutils" "github.com/slackapi/slack-cli/internal/hooks" "github.com/slackapi/slack-cli/internal/iostreams" "github.com/slackapi/slack-cli/internal/pkg/apps" @@ -307,7 +306,9 @@ func (r *LocalServer) StartDelegate(ctx context.Context) error { // To avoid removing any environment variables that are set in the current environment, we first set the cmd.Env to the current environment. // before adding any new environment variables. var cmdEnvVars = os.Environ() - cmdEnvVars = append(cmdEnvVars, goutils.MapToStringSlice(sdkManagedConnectionStartHookOpts.Env, "")...) + for name, value := range sdkManagedConnectionStartHookOpts.Env { + cmdEnvVars = append(cmdEnvVars, name+"="+value) + } cmd := sdkManagedConnectionStartHookOpts.Exec.Command(cmdEnvVars, os.Stdout, os.Stderr, nil, cmdArgs[0], cmdArgVars...) // Store command reference for lifecycle management