feat(security): add environment sanitization for exec tool#1261
feat(security): add environment sanitization for exec tool#1261keithy wants to merge 10 commits intosipeed:mainfrom
Conversation
- Add env.go with environment filtering logic - Add EnvSet and EnvAllowlist config options - Block sensitive variables (PATH, HOME, LD_*, PICOCLAW_*) from LLM override - Add PICOCLAW_* env vars to child processes - Document the feature
4ce2046 to
369edf3
Compare
- Remove unused BuildSanitizedEnv function - Extract MapToEnvSlice helper from MergeEnvVars - MergeEnvVars now returns map, caller converts to []string - Fix lint issues (gci, gofumpt, golines, whitespace) 💘 Generated with Crush
|
Standard: PICOCLAW: |
nikolasdehor
left a comment
There was a problem hiding this comment.
This is an important security improvement. Sanitizing the environment passed to child processes prevents accidental credential leakage (API keys, tokens, etc.) to LLM-invoked commands. The approach is well-structured.
Detailed feedback:
Architecture (positive):
- Separating env logic into
pkg/tools/shell/env.gois clean - The three-layer merge (cached base -> config env_set -> LLM extra) with different trust levels is the right design
- LLM blocklist preventing override of PATH/HOME/LD_PRELOAD is essential
- Windows case-insensitive handling via
envKeyis a good detail
Concerns:
- envSet map mutation --
WithAllowedEnvmodifies theenvSetmap in-place (result = envSet, then writes toresult). If the caller retains a reference toenvSet, they will see unexpected mutations. Either document this or copy the map first:
result := make(map[string]string, len(envSet))
for k, v := range envSet { result[k] = v }-
Same issue in
WithPicoclawEnvVars-- it also mutates the inputenvSetmap. -
Missing tests -- for a security-critical feature, unit tests are essential:
- Verify that API keys/tokens from parent env are NOT passed to children
- Verify that LLM cannot override PATH, LD_PRELOAD
- Verify that config
env_setoverrides inherited env - Verify that
env_allowlistcorrectly extends the default list - Verify Windows case-insensitive behavior
-
http_proxy/https_proxylowercase variants -- the allowlist hasHTTP_PROXYandHTTPS_PROXY, but many tools also use lowercasehttp_proxy/https_proxy. On Linux (case-sensitive), these would be stripped. Consider adding the lowercase variants. -
GOPATH, GOROOT, NODE_PATH -- tools invoked by the exec command may need these. Users can add them via
env_allowlist, but it might be worth mentioning in the docs. -
Breaking change potential -- existing setups that rely on env vars being passed through to exec commands (e.g.,
OPENAI_API_KEYused by Python scripts called from exec) will silently break after this change. Consider:- A migration note in the PR description
- A config option to opt out of sanitization (
env_sanitize: false) - At minimum, a log warning when env vars are stripped
Overall this is the right direction for security hardening. Please add tests and address the map mutation issue.
Resolved conflicts: - docs/tools_configuration.md: keep both Disabling Exec Tool and Environment Sanitization sections - pkg/config/config.go: keep both AllowRemote and EnvSet/EnvAllowlist fields - pkg/tools/shell.go: keep both imports and allowRemote/cachedEnv fields 💘 Generated with Crush Assisted-by: MiniMax-M2.5 via Crush <crush@charm.land>
- Use maps.Clone in WithAllowedEnv and WithPicoclawEnvVars to avoid mutating caller's map - Add lowercase http_proxy, https_proxy, no_proxy to default allowlist Address PR sipeed#1261 feedback. 💘 Generated with Crush Assisted-by: MiniMax-M2.5 via Crush <crush@charm.land>
Remove unused maps and logger imports after removing debug logging. 💘 Generated with Crush Assisted-by: MiniMax-M2.5 via Crush <crush@charm.land>
Debug log shows the merged env keys (cached + exec time + LLM extra) that will be passed to the executed command. Address PR sipeed#1261 feedback. 💘 Generated with Crush Assisted-by: MiniMax-M2.5 via Crush <crush@charm.land>
💘 Generated with Crush Assisted-by: MiniMax-M2.5 via Crush <crush@charm.land>
Test default allowlist, extra allowlist, env_set override, LLM blocklist, and config env preservation. Address PR sipeed#1261 feedback - add tests for security-critical feature. 💘 Generated with Crush Assisted-by: MiniMax-M2.5 via Crush <crush@charm.land>
💘 Generated with Crush Assisted-by: MiniMax-M2.5 via Crush <crush@charm.land>
💘 Generated with Crush Assisted-by: MiniMax-M2.5 via Crush <crush@charm.land>
|
Thanks @nikolasdehor for the excellent feedback
Held off on the following
Skipped
Tests Added
|
|
@keithy Hi! This PR has been inactive for a while now. If there's no update in the next 7 days, it will be closed automatically. If the environment sanitization feature is still being worked on, just drop a comment! |
📝 Description
This is an urgent requirement as the entire environment secrets and all is being passed through to LLM and the exec tool, secrets and all.
This PR aims to start looking at hardening the exec tool. I have diced up #1097 to pull out and refine the Environmment sanitisation feature.
🗣️ Type of Change
[X] 🐞 Bug fix
[ ] ✨ New feature
[x] 📖 Documentation update
[ ] ⚡ Code refactoring
🤖 AI Code Generation
[x] 👨💻 50/50 Human/AI written
🔗 Related Issues
🧪 Test Environment
Hardware: Rock64 (ARM64)
OS: Debian/Ubuntu (Linux) armbian, mise
Channels: CLI / Local Daemon
☑️ Checklist
[x] My code/docs follow the style of this project
[x] I have performed a self-review of my own changes
[x] I have updated the documentation
Summary
Next Steps
Round 2: Make the actual tool itself easier to swap/plugin different implementations, then we can try out different options.
Round 3: Implement a secure shell execution tool, resitant to injections etc.
My plan will be to banish so insecure and heavy weight bash, and ask the LLM to use the lean and mean
execlineinstead.