LocalExecutor built the shell env as {**os.environ, ...}, so every command
run_shell executes inherited the whole server process environment - including
COWORKER_API_TOKEN.
Measured, with the token and a provider key set on the server process:
run_shell(`echo "token=$COWORKER_API_TOKEN key=$OPENAI_API_KEY"`)
-> token=SIDECAR-SECRET-abc123 key=sk-user-key-xyz
That token authenticates every request to the local API
(server/app.py::require_sidecar_token). It is the only thing standing between a
process on this machine and the agent's shell and file tools, and the whole
point of run_shell is executing project code - build scripts, test suites, npm
lifecycle hooks. Any of those could read it back out and then drive the API
directly.
The repo already draws this line elsewhere: verify.scrubbed_env() exists so
"target-repo code never sees our credentials" (DOMAIN_MODEL §2) and is applied
to agent CLI sandboxes and local test runs. run_shell was the gap.
Scoped narrowly on purpose. Only OpenWorker's own credential is withheld; the
user's provider keys stay in the environment so builds, gh, and everything else
keep working. Widening this to provider keys is a real question but a UX
decision, not a bug fix, so it is left alone here.
Tests: tests/test_shell_env_isolation.py - the token is absent from both $VAR
expansion and a full `env` listing, the user's own keys survive, PATH survives,
and the explicit env= constructor argument is unchanged.