emrg: make the process boundary the default bash tool (bash tool v2, P6) - #1545
Merged
Merged
Conversation
added 3 commits
September 22, 2026 17:31
`[sandbox] bash_tool_v2` now defaults to v2. The frozen tool stays reachable as the rollback — one line in config.toml, or EMRG_BASH_TOOL_V2=0 for a single launch — and that path is pinned by its own tests, because a boundary that cannot be turned off in the field is not deployable. Flipping the switch made a measured defect visible: a confined run cannot write the home directory, which is where uv, pip and npm keep their caches. uv fails outright, npm's ~/.npm cannot be created, and pip silently disables its cache. The tool now points those four variables at <temp>/emrg-confined-cache for the confined child — inside a root the policy already grants, so nothing is widened, and a variable the deployer set is never overridden. Six mutation arms each kill a named test.
…ts (bash tool v2, P6) The four new tests built a policy on the literal /tmp, which is absolute on POSIX and not on Windows, so SandboxPolicy refused it on the windows leg while the dev host stayed green. They now take tmp_path — a directory that exists, as a workspace root should be — and the section says why.
…easure (bash tool v2, P6)
This was referenced Sep 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bash tool v2, phase P6 — the switch flips. Design
bash-tool-v2-design.md§D7/§D10.What changes for an instance that says nothing
[sandbox] bash_tool_v2now defaults totrue: the tool namedbashis the one whose confinement is the OS process boundary (macOS Seatbelt, Linux bubblewrap, Windows ACL-restricted tokens) rather than a static scan of the command text. P1/P3/P4 landed the three backends; this is the phase that makes them the thing running.The frozen tool stays reachable, and the rollback is a supported path, not an accident:
EMRG_BASH_TOOL_V2=0does the same for a single launch, without editing anything. Both are pinned by tests — a boundary that cannot be turned off in the field is not deployable.danger-full-accessis unaffected and still runs bare; a task configured with it (the evolution task on this host, for instance) sees no behaviour change at all.The defect the flip made visible
Flipping the switch turned a latent break into a real one, and it is the reason this PR is not a one-line default change. A confined run cannot write the home directory, which is where package managers keep their caches. Measured on the dev host through this tool at
workspace-write:uv~/.cache/uvuv runfails:error: Failed to initialize cache at /Users/<host>/.cache/uvnpm~/.npmtouch: Operation not permittedpip~/Library/Caches/pipThe directory … is not writable … The cache has been disabledSo the tool now sets four variables for the confined child —
XDG_CACHE_HOME,UV_CACHE_DIR,PIP_CACHE_DIR,npm_config_cache— to<temp>/emrg-confined-cache. Three properties keep this from being a boundary widening, and each is a test:writable_roots, the same derivation the Seatbelt profile is built from — not against a second copy of the rules);read-onlyrun relocates nothing — there is no writable root to move a cache into, and naming one would describe a boundary the run does not have;canonical_path), which the first cut of this change was not: on darwingettempdir()reports/var/folders/…while the granted root is/private/var/folders/…, and the containment test caught it (design §3.5's spelling trap, again).pip's row is why the relocation is not optional even though onlyuvfails loudly: a cache that is silently disabled is the failure that costs an afternoon.Declared deviations
dshdoes not need it: it is launched from the deployer's shell, so "setUV_CACHE_DIR" is an instruction the deployer can carry out. EMRG's daemon is normally started by the GUI or a launcher and inherits neither, so the same instruction would be one nobody can follow. The addition is registered here rather than hidden: it relocates caches, never credentials or configuration (~/.config,~/.ssh, the credential store stay put, and a confined run that needs to write those fails loudly).bwraprefuses every command. That is the design's own fail-closed contract, and it is whyDEVELOPMENT.mdsays to leave the switch off there untilbwrapis installed and user namespaces are allowed. It is the honest cost of removing a boundary that only looked like one, and it is stated rather than softened. Windows is the same shape where the ACL backend cannot be established.Measured
read-only(B) · the deployer's value overridden (C) · the base left uncanonicalised (D) · the default flipped back (E) · the env rollback path dropped (F).uv run— which failed before this change — succeeds.