From b43acf4aba894860aa6b6c076d5cfae0e5434080 Mon Sep 17 00:00:00 2001 From: Keith Patrick Date: Sun, 8 Mar 2026 19:55:11 +0000 Subject: [PATCH] feat(security): add config env_set support - Add EnvSet field to ExecConfig for config file - Merge env_set into cachedEnv at ExecTool init - LLM env overrides still checked against blocklist --- pkg/config/config.go | 9 +++++---- pkg/tools/shell.go | 8 +++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index b3ad050b7..47b87ccf5 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -641,10 +641,11 @@ type CronToolsConfig struct { type ExecConfig struct { ToolConfig ` envPrefix:"PICOCLAW_TOOLS_EXEC_"` - EnableDenyPatterns bool ` env:"PICOCLAW_TOOLS_EXEC_ENABLE_DENY_PATTERNS" json:"enable_deny_patterns"` - CustomDenyPatterns []string ` env:"PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS" json:"custom_deny_patterns"` - CustomAllowPatterns []string ` env:"PICOCLAW_TOOLS_EXEC_CUSTOM_ALLOW_PATTERNS" json:"custom_allow_patterns"` - TimeoutSeconds int ` env:"PICOCLAW_TOOLS_EXEC_TIMEOUT_SECONDS" json:"timeout_seconds"` // 0 means use default (60s) + EnableDenyPatterns bool ` env:"PICOCLAW_TOOLS_EXEC_ENABLE_DENY_PATTERNS" json:"enable_deny_patterns"` + CustomDenyPatterns []string ` env:"PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS" json:"custom_deny_patterns"` + CustomAllowPatterns []string ` env:"PICOCLAW_TOOLS_EXEC_CUSTOM_ALLOW_PATTERNS" json:"custom_allow_patterns"` + TimeoutSeconds int ` env:"PICOCLAW_TOOLS_EXEC_TIMEOUT_SECONDS" json:"timeout_seconds"` // 0 means use default (60s) + EnvSet map[string]string ` json:"env_set"` // env vars to set for all exec commands } type SkillsToolsConfig struct { diff --git a/pkg/tools/shell.go b/pkg/tools/shell.go index c13208b63..8a48b8661 100644 --- a/pkg/tools/shell.go +++ b/pkg/tools/shell.go @@ -138,6 +138,12 @@ func NewExecToolWithConfig(workingDir string, restrict bool, config *config.Conf timeout = time.Duration(config.Tools.Exec.TimeoutSeconds) * time.Second } + // Get envSet from config (if provided) + var envSet map[string]string + if config != nil && config.Tools.Exec.EnvSet != nil { + envSet = config.Tools.Exec.EnvSet + } + return &ExecTool{ workingDir: workingDir, timeout: timeout, @@ -145,7 +151,7 @@ func NewExecToolWithConfig(workingDir string, restrict bool, config *config.Conf allowPatterns: nil, customAllowPatterns: customAllowPatterns, restrictToWorkspace: restrict, - cachedEnv: shell.BuildSanitizedEnv(os.Environ(), nil, nil, nil), + cachedEnv: shell.BuildSanitizedEnv(os.Environ(), nil, envSet, nil), }, nil }