MCPcopy Create free account
hub / github.com/diillson/chatcli / Execute

Method Execute

cli/agent/command_executor.go:55–133  ·  view source on GitHub ↗

Execute executa um comando e retorna o resultado

(ctx context.Context, command string, interactive bool)

Source from the content-addressed store, hash-verified

53
54// Execute executa um comando e retorna o resultado
55func (e *CommandExecutor) Execute(ctx context.Context, command string, interactive bool) (*ExecutionResult, error) {
56 // Security (H8): Allowlist-based command validation (defense in depth)
57 if e.allowlist.GetMode() == SecurityModeStrict {
58 if allowed, _, reason := e.allowlist.IsAllowed(command); !allowed {
59 e.logger.Warn("Command blocked by allowlist", zap.String("command", command), zap.String("reason", reason))
60 return &ExecutionResult{
61 Command: command,
62 Error: reason,
63 }, fmt.Errorf("command blocked: %s (set CHATCLI_AGENT_SECURITY_MODE=permissive to use denylist fallback)", reason)
64 }
65 } else if e.allowlist.GetMode() == SecurityModePermissive {
66 // In permissive mode, check allowlist first; if not allowed, fall through to denylist
67 if allowed, _, _ := e.allowlist.IsAllowed(command); !allowed {
68 e.logger.Debug("Command not in allowlist, falling through to denylist", zap.String("command", command))
69 }
70 }
71
72 // Legacy denylist validation (always active as second layer)
73 if err := e.validator.ValidateCommand(command); err != nil {
74 e.logger.Warn("Comando inválido", zap.String("command", command), zap.Error(err))
75 return &ExecutionResult{
76 Command: command,
77 Error: err.Error(),
78 }, err
79 }
80
81 // --- LÓGICA DE SELEÇÃO DE SHELL E FLAG ---
82 shell := os.Getenv("SHELL")
83 shellFlag := "-c" // Padrão Unix (bash, zsh, sh)
84
85 if shell == "" {
86 if runtime.GOOS == "windows" {
87 shell = "powershell.exe" // Fallback seguro para Windows
88 } else {
89 shell = "/bin/sh"
90 }
91 }
92
93 // Validate $SHELL against known shell binaries to prevent env manipulation
94 if runtime.GOOS != "windows" {
95 shellBase := filepath.Base(shell)
96 allowedShells := map[string]bool{
97 "sh": true, "bash": true, "zsh": true, "dash": true,
98 "fish": true, "ksh": true, "csh": true, "tcsh": true,
99 }
100 if !allowedShells[shellBase] {
101 e.logger.Warn("Unrecognized shell, falling back to /bin/sh",
102 zap.String("shell", shell))
103 shell = "/bin/sh"
104 }
105 }
106
107 // Ajuste da flag baseado no binário do shell
108 if runtime.GOOS == "windows" {
109 lowerShell := strings.ToLower(shell)
110 if strings.Contains(lowerShell, "powershell") || strings.Contains(lowerShell, "pwsh") {
111 shellFlag = "-Command"
112 } else if strings.Contains(lowerShell, "cmd") {

Callers

nothing calls this directly

Implementers 2

MockCommandExecutorutils/git_utils_test.go
OSCommandExecutorutils/exec_utils.go

Calls 9

executeInteractiveMethod · 0.95
executeNonInteractiveMethod · 0.95
WarnMethod · 0.80
ErrorfMethod · 0.80
ValidateCommandMethod · 0.80
ErrorMethod · 0.65
GetModeMethod · 0.45
IsAllowedMethod · 0.45
StringMethod · 0.45

Tested by

no test coverage detected