diff --git a/config/config.example.json b/config/config.example.json index 9575039f8..5965df309 100644 --- a/config/config.example.json +++ b/config/config.example.json @@ -224,6 +224,7 @@ "exec_timeout_minutes": 5 }, "exec": { + "timeout_seconds": 0, "enable_deny_patterns": false, "custom_deny_patterns": [] }, diff --git a/pkg/config/config.go b/pkg/config/config.go index ca5803c35..607b1e7e1 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -466,6 +466,7 @@ type CronToolsConfig struct { } type ExecConfig struct { + TimeoutSeconds int `json:"timeout_seconds" env:"PICOCLAW_TOOLS_EXEC_TIMEOUT_SECONDS"` // 0 means use default (60s) EnableDenyPatterns bool `json:"enable_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_ENABLE_DENY_PATTERNS"` CustomDenyPatterns []string `json:"custom_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS"` } diff --git a/pkg/tools/shell.go b/pkg/tools/shell.go index ad1664b5b..5ced7f258 100644 --- a/pkg/tools/shell.go +++ b/pkg/tools/shell.go @@ -75,6 +75,7 @@ func NewExecTool(workingDir string, restrict bool) *ExecTool { func NewExecToolWithConfig(workingDir string, restrict bool, config *config.Config) *ExecTool { denyPatterns := make([]*regexp.Regexp, 0) + timeout := 60 * time.Second // default timeout if config != nil { execConfig := config.Tools.Exec @@ -96,13 +97,18 @@ func NewExecToolWithConfig(workingDir string, restrict bool, config *config.Conf // If deny patterns are disabled, we won't add any patterns, allowing all commands. fmt.Println("Warning: deny patterns are disabled. All commands will be allowed.") } + + // Apply configured timeout if set (0 means use default) + if execConfig.TimeoutSeconds > 0 { + timeout = time.Duration(execConfig.TimeoutSeconds) * time.Second + } } else { denyPatterns = append(denyPatterns, defaultDenyPatterns...) } return &ExecTool{ workingDir: workingDir, - timeout: 60 * time.Second, + timeout: timeout, denyPatterns: denyPatterns, allowPatterns: nil, restrictToWorkspace: restrict,