Follow-up from #905 (PR #994), found by the cross-family review.
Problem
cf work start --engine claude-code and --engine codex spawn a CLI subprocess without a sanitized env=, so the child receives the operator's full environment — every exported secret — and the real HOME, which points at ~/.codeframe and the credential store.
Failure scenario: a task prompt in an untrusted repo instructs the delegated agent to read credentials. For Claude Code specifically, the Bash guard is the same regex filter fixed in #905, which is defense-in-depth and not a containment boundary — an obfuscated path defeats it.
Why it was not fixed in #905
#905 sandboxed the built-in engines (run_command, run_tests, legacy plan executor) via core/agent_env.py:build_agent_env(). The delegated adapters are a different problem: those CLIs legitimately need provider credentials to function at all (ANTHROPIC_API_KEY for Claude Code, OpenAI auth for Codex). Handing them a credential-free environment would simply break them, so this needs a design decision — which credentials to forward, and whether HOME can be sandboxed independently of them.
Suggested approach
- Forward only the provider credential the chosen adapter needs, not the whole environment.
- Sandbox
HOME/XDG_* separately — the delegated CLI needs its own config dir, which may argue for a per-adapter home rather than the shared .codeframe/agent-home. Note these CLIs keep their own auth in ~/.claude, ~/.codex, so a naive sandbox will log them out; that is the design question.
- Per launch scope, the delegated engines are launch-critical (multi-model acceptance), so this should not sit behind E2B work.
Evidence
codeframe/core/adapters/subprocess_adapter.py:117
codeframe/core/adapters/codex.py:98
- Shared helper:
codeframe/core/agent_env.py
Follow-up from #905 (PR #994), found by the cross-family review.
Problem
cf work start --engine claude-codeand--engine codexspawn a CLI subprocess without a sanitizedenv=, so the child receives the operator's full environment — every exported secret — and the realHOME, which points at~/.codeframeand the credential store.Failure scenario: a task prompt in an untrusted repo instructs the delegated agent to read credentials. For Claude Code specifically, the Bash guard is the same regex filter fixed in #905, which is defense-in-depth and not a containment boundary — an obfuscated path defeats it.
Why it was not fixed in #905
#905 sandboxed the built-in engines (
run_command,run_tests, legacy plan executor) viacore/agent_env.py:build_agent_env(). The delegated adapters are a different problem: those CLIs legitimately need provider credentials to function at all (ANTHROPIC_API_KEYfor Claude Code, OpenAI auth for Codex). Handing them a credential-free environment would simply break them, so this needs a design decision — which credentials to forward, and whetherHOMEcan be sandboxed independently of them.Suggested approach
HOME/XDG_*separately — the delegated CLI needs its own config dir, which may argue for a per-adapter home rather than the shared.codeframe/agent-home. Note these CLIs keep their own auth in~/.claude,~/.codex, so a naive sandbox will log them out; that is the design question.Evidence
codeframe/core/adapters/subprocess_adapter.py:117codeframe/core/adapters/codex.py:98codeframe/core/agent_env.py