fix(bash): validate managed env namespace
This commit is contained in:
@@ -22,7 +22,7 @@ Design surveyed against the bash tools of Claude Code, OpenCode, Codex, and pi;
|
||||
- **Spawn per call, no shell state** — every call is a fresh non-login `bash -c` (deterministic; no rc files). All four surveyed tools spawn per call. `XXX(stateful-shell)` in `src/run.ts` records the two proven stateful designs (Claude Code's cwd-only persistence; Codex's PTY exec sessions) for when real workflows demand them.
|
||||
- **Process-group kills with escalation** — children are spawned `detached` (own process group); kills send SIGTERM to the group, then SIGKILL after the `graceMs` grace (default 3s — OpenCode's escalation; pipelines and subshells die with the parent). ESRCH is tolerated; daemons that re-parent away from the group can still survive — same caveat as the surveyed tools.
|
||||
- **Tail-keep truncation + spill files** — output beyond `maxOutputBytes` keeps the in-memory TAIL (errors/results cluster at the end — pi/OpenCode rationale) while the FULL stream is appended to a temp file whose path is reported when available. If the final spill close reports a delayed writeback failure, the executor still returns the tail but withholds the path rather than advertising a possibly incomplete file.
|
||||
- **Model-friendly env + credential/namespace scrub** — start with `process.env` minus credential-shaped vars (`*KEY*`/`*SECRET*`/`*TOKEN*`) and every `DSH_*`, then apply `NO_COLOR=1 TERM=dumb PAGER=cat GIT_PAGER=cat`. Ordinary spec `env` is merged next and may restore caller-held credential-shaped values, but is rejected if it tries to set reserved `DSH_*`; the trusted spec `dshEnv` snapshot is merged last. This keeps ambient secrets out and prevents a nested/previous harness identity from surviving when the current registry omits it. The spec's `stdin`, when supplied, is written to the child and closed; with none supplied, fd 0 is `/dev/null`. See [the bash-stdin-env RFC](../../../docs/rfc/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-surface.md) and [the session environment RFC](../../../docs/rfc/implemented/feature/2026-07-10-agent-session-identity-and-log-location.md).
|
||||
- **Model-friendly env + credential/namespace scrub** — start with `process.env` minus credential-shaped vars (`*KEY*`/`*SECRET*`/`*TOKEN*`) and every `DSH_*`, then apply `NO_COLOR=1 TERM=dumb PAGER=cat GIT_PAGER=cat`. Ordinary spec `env` is merged next and may restore caller-held credential-shaped values, but is rejected if it tries to set reserved `DSH_*`; the managed spec `dshEnv` snapshot is rejected if it contains ordinary names and otherwise merges last. This keeps ambient secrets out, catches wrong-channel plugin configuration before spawn, and prevents a nested/previous harness identity from surviving when the current registry omits it. The spec's `stdin`, when supplied, is written to the child and closed; with none supplied, fd 0 is `/dev/null`. See [the bash-stdin-env RFC](../../../docs/rfc/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-surface.md) and [the session environment RFC](../../../docs/rfc/implemented/feature/2026-07-10-agent-session-identity-and-log-location.md).
|
||||
- **Background tasks** — `start()` returns immediately, no timeout applies (Claude Code detaches timeouts when backgrounding), `readOutput()` is incremental with whole-stream byte offsets, and disposal kills everything. The spec's opaque `owner` token is stored on the tracked task and returned by `ownerOf(id)` — the executor never interprets it (the consumer's access policy does), and because it lives with the task here it survives a `tool-bash` HMR reload.
|
||||
|
||||
## Sandboxing
|
||||
|
||||
Reference in New Issue
Block a user