Enhancement Category
Code mode improvements
Problem or Use Case
Code mode currently executes LLM-generated Go code with full system access. While powerful, this poses security risks:
- Accidental damage: LLM could mistakenly delete important files (e.g.,
os.Remove("/important/file"))
- Unintended network access: Code could make unexpected API calls or exfiltrate data
- Process execution: Could run dangerous commands (
exec.Command("rm", "-rf", "/"))
- User trust: Users may hesitate to use code mode without safeguards, especially in production environments
Current alternatives (running CPE in containers or VMs) are heavy and platform-specific. We need a lightweight, cross-platform solution that:
- Allows users to define permissions for file access, process execution, and network operations
- Works on macOS, Linux, and Windows without additional dependencies
- Doesn't require Docker or virtualization
- Aligns with CPE's philosophy of being a lightweight CLI tool
Proposed Solution
Use Go's -toolexec flag to inject a compilation wrapper that rewrites LLM-generated code to include permission checks before sensitive operations.
How it works:
- Wrapper intercepts compilation: When
go build runs, a wrapper program sits between the build command and the actual compiler
- AST rewriting: The wrapper parses the generated
run.go file, detects calls to sensitive functions (os.ReadFile, exec.Command, http.Get, etc.), and injects permission checks
- Runtime enforcement: A permission checking library (injected into
main.go) validates operations against user-defined rules
- Clear failures: Operations that violate policies fail with descriptive error messages
Example transformation:
Before (LLM-generated):
data, err := os.ReadFile("config.json")
After (rewritten by wrapper):
if err := __cpe_check_file_read("config.json"); err != nil {
return fmt.Errorf("permission denied: %w", err)
}
data, err := os.ReadFile("config.json")
Configuration:
defaults:
codeMode:
enabled: true
sandboxing:
enabled: false # Opt-in initially
allowedPaths:
- "/tmp/cpe-*"
- "./data/*"
deniedPaths:
- "/etc/*"
- "~/.ssh/*"
allowedCommands:
- "git"
- "rg"
deniedCommands:
- "rm"
- "sudo"
allowNetwork: true
interactive: false # If true, prompt user for each operation
Sensitive operations to track:
- File:
os.Open, os.ReadFile, os.WriteFile, os.Remove, os.RemoveAll, etc.
- Exec:
exec.Command, exec.CommandContext
- Network:
http.Get, http.Post, net.Dial
- Dangerous:
import "unsafe", import "reflect", import "C"
Alternatives Considered
| Alternative |
Pros |
Cons |
Verdict |
| Containers (Docker/Podman) |
Strong isolation, proven technology |
Requires Docker daemon, heavy, platform-specific, slow startup |
Too heavy for CPE's use case |
| VMs (Firecracker) |
Ultimate isolation |
Very heavy, Linux-only, slow startup, complex setup |
Overkill for code mode |
| Static analysis |
Pre-execution validation, no runtime cost |
Can't catch all cases (dynamic paths), high false positive rate |
Could complement but not replace runtime checks |
| ptrace/seccomp |
Kernel-level enforcement |
Linux-only, complex configuration, can break legitimate programs |
Platform limitation is a dealbreaker |
| Filesystem overlays |
Clean file isolation |
Doesn't cover network/exec, requires OS-specific features |
Only partial solution |
| -toolexec approach |
Lightweight, cross-platform, native Go, fine-grained control |
Implementation complexity, potential bypasses via unsafe/reflect |
✅ Best fit for CPE |
The -toolexec approach is proven in production by the xgo project, which uses the same technique for monkey patching Go functions.
Impact Scope
Everyone using CPE
While the feature would be opt-in initially, it addresses a fundamental security concern that affects all code mode users. Benefits:
- Current users: Can use code mode more confidently, especially in production environments
- New users: More likely to adopt code mode knowing safeguards exist
- Enterprise users: Meets security requirements for using AI-assisted tools
- All platforms: Works on macOS, Linux, and Windows without additional dependencies
Additional Context
Implementation phases:
- Phase 1 - PoC (1-2 days): Basic wrapper that detects and logs
os.ReadFile calls
- Phase 2 - Basic permissions (3-5 days): File read/write allowlist/denylist enforcement
- Phase 3 - Extended coverage (1 week): Process execution, network, edge cases
- Phase 4 - Production ready (1-2 weeks): Tests, benchmarks, docs, feature flag
Documentation created:
- Analysis:
docs/toolexec-sandboxing-analysis.md
- Summary:
docs/toolexec-summary.md
- Working PoC:
docs/toolexec-poc/ (includes AST rewriter example)
Key advantages:
✅ Lightweight (no containers/VMs)
✅ Cross-platform (macOS, Linux, Windows)
✅ Fine-grained control (read vs write, specific paths)
✅ Native Go integration (uses -toolexec flag)
✅ Optional (can be disabled for trusted scenarios)
✅ Zero overhead (only checks sensitive operations)
Key challenges & mitigations:
⚠️ AST rewriting complexity → Comprehensive tests, incremental rollout
⚠️ Potential bypasses (unsafe/reflect) → Detect and flag/deny these imports
⚠️ Maintenance across Go versions → Version locking, regular updates
⚠️ Dynamic path validation → Hook syscall-level functions for runtime checks
Open questions:
- Should we support interactive mode (prompt for each sensitive operation)?
- Default policy: allow-by-default or deny-by-default?
- How to handle unsafe/reflect: ban outright or warn?
- Per-invocation permissions or global config?
- Should we provide presets (read-only mode, network-only mode)?
References:
Enhancement Category
Code mode improvements
Problem or Use Case
Code mode currently executes LLM-generated Go code with full system access. While powerful, this poses security risks:
os.Remove("/important/file"))exec.Command("rm", "-rf", "/"))Current alternatives (running CPE in containers or VMs) are heavy and platform-specific. We need a lightweight, cross-platform solution that:
Proposed Solution
Use Go's
-toolexecflag to inject a compilation wrapper that rewrites LLM-generated code to include permission checks before sensitive operations.How it works:
go buildruns, a wrapper program sits between the build command and the actual compilerrun.gofile, detects calls to sensitive functions (os.ReadFile,exec.Command,http.Get, etc.), and injects permission checksmain.go) validates operations against user-defined rulesExample transformation:
Before (LLM-generated):
After (rewritten by wrapper):
Configuration:
Sensitive operations to track:
os.Open,os.ReadFile,os.WriteFile,os.Remove,os.RemoveAll, etc.exec.Command,exec.CommandContexthttp.Get,http.Post,net.Dialimport "unsafe",import "reflect",import "C"Alternatives Considered
The
-toolexecapproach is proven in production by the xgo project, which uses the same technique for monkey patching Go functions.Impact Scope
Everyone using CPE
While the feature would be opt-in initially, it addresses a fundamental security concern that affects all code mode users. Benefits:
Additional Context
Implementation phases:
os.ReadFilecallsDocumentation created:
docs/toolexec-sandboxing-analysis.mddocs/toolexec-summary.mddocs/toolexec-poc/(includes AST rewriter example)Key advantages:
✅ Lightweight (no containers/VMs)
✅ Cross-platform (macOS, Linux, Windows)
✅ Fine-grained control (read vs write, specific paths)
✅ Native Go integration (uses
-toolexecflag)✅ Optional (can be disabled for trusted scenarios)
✅ Zero overhead (only checks sensitive operations)
Key challenges & mitigations:
⚠️ AST rewriting complexity → Comprehensive tests, incremental rollout
⚠️ Potential bypasses (unsafe/reflect) → Detect and flag/deny these imports
⚠️ Maintenance across Go versions → Version locking, regular updates
⚠️ Dynamic path validation → Hook syscall-level functions for runtime checks
Open questions:
References:
-toolexecdocs: https://pkg.go.dev/cmd/go