From e0ffee833974e6e4f96e0f6ee430c7eb4072aa4a Mon Sep 17 00:00:00 2001 From: Keith Patrick Date: Mon, 9 Mar 2026 02:05:44 +0000 Subject: [PATCH] Add PICOCLAW_EXEC_TIME and PICOCLAW_EXEC_TIMEOUT env vars - Add timestamp (RFC3339) and timeout to child process env - Add PICOCLAW_* vars to blocklist so LLM cannot override --- pkg/tools/shell.go | 10 ++++++++-- pkg/tools/shell/env.go | 10 ++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pkg/tools/shell.go b/pkg/tools/shell.go index 317ea35f2..587827251 100644 --- a/pkg/tools/shell.go +++ b/pkg/tools/shell.go @@ -184,7 +184,7 @@ func (t *ExecTool) Parameters() map[string]any { }, "env": map[string]any{ "type": "object", - "description": "Additional environment variables to set for this command. Available: PICOCLAW_HOME, PICOCLAW_CONFIG, PICOCLAW_AGENT_WORKSPACE, PICOCLAW_EXE, PICOCLAW_SERVICE_NAME. Cannot override: PATH, HOME, USER, LOGNAME, SHELL, LD_PRELOAD, LD_LIBRARY_PATH, LD_AUDIT, LD_DEBUG", + "description": "Additional environment variables to set for this command. Available: PICOCLAW_HOME, PICOCLAW_CONFIG, PICOCLAW_AGENT_WORKSPACE, PICOCLAW_EXE, PICOCLAW_SERVICE_NAME, PICOCLAW_EXEC_TIME (RFC3339), PICOCLAW_EXEC_TIMEOUT. Cannot override: PATH, HOME, USER, LOGNAME, SHELL, LD_PRELOAD, LD_LIBRARY_PATH, LD_AUDIT, LD_DEBUG, PICOCLAW_*", "additionalProperties": map[string]any{ "type": "string", }, @@ -252,9 +252,15 @@ func (t *ExecTool) Execute(ctx context.Context, args map[string]any) *ToolResult } } + // Add PICOCLAW_EXEC_TIME - timestamp when command is executed + execTimeEnv := map[string]string{ + "PICOCLAW_EXEC_TIME": time.Now().Format(time.RFC3339), + "PICOCLAW_EXEC_TIMEOUT": t.timeout.String(), + } + // Use sanitized environment - strips secrets, prevents env-based attacks // Pass extraEnv from LLM to apply blocklist filtering - cmd.Env = shell.BuildSanitizedEnv(t.cachedEnv, nil, nil, extraEnv) + cmd.Env = shell.BuildSanitizedEnv(t.cachedEnv, nil, execTimeEnv, extraEnv) if cwd != "" { cmd.Dir = cwd diff --git a/pkg/tools/shell/env.go b/pkg/tools/shell/env.go index 975b0263a..3abd5c499 100644 --- a/pkg/tools/shell/env.go +++ b/pkg/tools/shell/env.go @@ -55,6 +55,15 @@ var LLMBlocklist = map[string]bool{ "LD_LIBRARY_PATH": true, // Could hijack library resolution "LD_AUDIT": true, // Could inject code "LD_DEBUG": true, // Could leak info + + // PICOCLAW_* vars - controlled by the agent, not LLM + "PICOCLAW_HOME": true, + "PICOCLAW_CONFIG": true, + "PICOCLAW_AGENT_WORKSPACE": true, + "PICOCLAW_EXE": true, + "PICOCLAW_SERVICE_NAME": true, + "PICOCLAW_EXEC_TIME": true, + "PICOCLAW_EXEC_TIMEOUT": true, } // windowsEnvAllowlist contains additional variables needed on Windows. @@ -78,6 +87,7 @@ var windowsEnvAllowlist = map[string]bool{ // envSet provides explicit key=value pairs from config (override inherited). // extraEnv provides additional key=value pairs from tool call (merged with envSet). func BuildSanitizedEnv(baseEnv []string, extraAllowlist []string, envSet, extraEnv map[string]string) []string { + // Use provided env or fall back to os.Environ inherited := baseEnv if inherited == nil {