Add PICOCLAW_* env vars to child processes

- Ensure PICOCLAW_HOME, PICOCLAW_CONFIG, PICOCLAW_EXE, PICOCLAW_SERVICE_NAME
  are passed to exec'd child processes
- Remove hardcoded PICOCLAW_* from DefaultEnvAllowlist (now handled dynamically)
This commit is contained in:
Keith Patrick 2026-03-09 01:03:24 +00:00
parent ddd394796c
commit 347aade2fb
2 changed files with 37 additions and 4 deletions

View file

@ -148,6 +148,9 @@ func NewExecToolWithConfig(workingDir string, restrict bool, config *config.Conf
envAllowlist = config.Tools.Exec.EnvAllowlist envAllowlist = config.Tools.Exec.EnvAllowlist
} }
// Ensure PICOCLAW_* vars are set for child processes
envSet = shell.WithPicoclawEnvVars(envSet)
return &ExecTool{ return &ExecTool{
workingDir: workingDir, workingDir: workingDir,
timeout: timeout, timeout: timeout,

View file

@ -2,6 +2,7 @@ package shell
import ( import (
"os" "os"
"path/filepath"
"runtime" "runtime"
"strings" "strings"
) )
@ -34,10 +35,6 @@ var DefaultEnvAllowlist = map[string]bool{
"HTTP_PROXY": true, "HTTP_PROXY": true,
"HTTPS_PROXY": true, "HTTPS_PROXY": true,
"NO_PROXY": true, "NO_PROXY": true,
"PICOCLAW_HOME": true,
"PICOCLAW_CONFIG": true,
"PICOCLAW_SERVICE_NAME": true,
"PICOCLAW_EXE": true,
} }
// defaultEnvAllowPrefixes are env var prefixes that are always allowed. // defaultEnvAllowPrefixes are env var prefixes that are always allowed.
@ -156,3 +153,36 @@ func isAllowedPrefix(name string) bool {
} }
return false return false
} }
// WithPicoclawEnvVars ensures PICOCLAW_* vars are set in envSet.
// These are needed for child processes to locate config, workspace, etc.
func WithPicoclawEnvVars(envSet map[string]string) map[string]string {
if envSet == nil {
envSet = make(map[string]string)
}
// Always compute PICOCLAW_* vars - priority: env var > default
if v := os.Getenv("PICOCLAW_HOME"); v != "" {
envSet["PICOCLAW_HOME"] = v
} else if home, _ := os.UserHomeDir(); home != "" {
envSet["PICOCLAW_HOME"] = filepath.Join(home, ".picoclaw")
}
if v := os.Getenv("PICOCLAW_CONFIG"); v != "" {
envSet["PICOCLAW_CONFIG"] = v
} else if home := envSet["PICOCLAW_HOME"]; home != "" {
envSet["PICOCLAW_CONFIG"] = filepath.Join(home, "config.json")
}
if exe, err := os.Executable(); err == nil {
envSet["PICOCLAW_EXE"] = exe
}
if v := os.Getenv("PICOCLAW_SERVICE_NAME"); v != "" {
envSet["PICOCLAW_SERVICE_NAME"] = v
} else {
envSet["PICOCLAW_SERVICE_NAME"] = "picoclaw"
}
return envSet
}