diff --git a/internal/llm/tools/bash.go b/internal/llm/tools/bash.go index add62210f7179a15912959a07c64f5da333b582d..ad8c799ac61485b3ea7d99b03643644dfa5ee319 100644 --- a/internal/llm/tools/bash.go +++ b/internal/llm/tools/bash.go @@ -298,6 +298,9 @@ func blockFuncs() []shell.BlockFunc { shell.ArgumentsBlocker("pnpm", []string{"add"}, []string{"--global"}), shell.ArgumentsBlocker("pnpm", []string{"add"}, []string{"-g"}), shell.ArgumentsBlocker("yarn", []string{"global", "add"}, nil), + + // `go test -exec` can run arbitrary commands + shell.ArgumentsBlocker("go", []string{"test"}, []string{"-exec"}), } } diff --git a/internal/shell/command_block_test.go b/internal/shell/command_block_test.go index 99eb5256446f604bb473f3130fd24950d1e058b3..22e91b14189d00bd87a1ea14767b64b4e102ae88 100644 --- a/internal/shell/command_block_test.go +++ b/internal/shell/command_block_test.go @@ -231,6 +231,24 @@ func TestArgumentsBlocker(t *testing.T) { input: []string{"pacman", "-Q", "package"}, shouldBlock: false, }, + + // `go test -exec` + { + name: "go test exec", + cmd: "go", + args: []string{"test"}, + flags: []string{"-exec"}, + input: []string{"go", "test", "-exec", "bash -c 'echo hello'"}, + shouldBlock: true, + }, + { + name: "go test exec", + cmd: "go", + args: []string{"test"}, + flags: []string{"-exec"}, + input: []string{"go", "test", `-exec="bash -c 'echo hello'"`}, + shouldBlock: true, + }, } for _, tt := range tests { @@ -329,6 +347,24 @@ func TestSplitArgsFlags(t *testing.T) { wantArgs: []string{"package"}, wantFlags: []string{"-S"}, }, + { + name: "flag with equals sign", + input: []string{"-exec=bash", "package"}, + wantArgs: []string{"package"}, + wantFlags: []string{"-exec"}, + }, + { + name: "long flag with equals sign", + input: []string{"--config=/path/to/config", "run"}, + wantArgs: []string{"run"}, + wantFlags: []string{"--config"}, + }, + { + name: "flag with complex value", + input: []string{`-exec="bash -c 'echo hello'"`, "test"}, + wantArgs: []string{"test"}, + wantFlags: []string{"-exec"}, + }, } for _, tt := range tests { diff --git a/internal/shell/shell.go b/internal/shell/shell.go index 73dbfbffcc65cffba3e96443076dd80e940d7742..618899d808b90163ac82c6970440c26c0110db76 100644 --- a/internal/shell/shell.go +++ b/internal/shell/shell.go @@ -197,7 +197,12 @@ func splitArgsFlags(parts []string) (args []string, flags []string) { flags = make([]string, 0, len(parts)) for _, part := range parts { if strings.HasPrefix(part, "-") { - flags = append(flags, part) + // Extract flag name before '=' if present + flag := part + if idx := strings.IndexByte(part, '='); idx != -1 { + flag = part[:idx] + } + flags = append(flags, flag) } else { args = append(args, part) }