emrg: bash tool sandbox — file-level isolation for task sessions - #886
Merged
Conversation
…t 2026-08-20T15:46:50) Per-task sandbox tier (read-only / workspace-write / danger-full-access, default = danger-full-access = current behavior) injected into the bash tool's static command scan: - read-only: blocks destructive writes (rm -r / rmdir / mv / cp -r and shell redirects to non-/dev/null targets) - workspace-write: blocks writes to protected daemon files (config.toml / emrgd.token / tasks.yml / projects.yml / rants.jsonl), to ~/.emrg itself, and to absolute paths outside the workspace (OS temp dir allowed, mirroring dsh's workspace + temp area) - enforcement honestly reports partial (static heuristic, no OS-level boundary — no bwrap/Seatbelt/ACL) Wiring: TaskRequest.sandbox (protocol) → daemon tool loop injects it into bash args → scheduler resolves tier per task (explicit tasks.yml sandbox field wins; emrg-task → workspace-write, *-opensource-task → read-only, custom tasks → full access). Upgrade sessions run workspace-write. task_create/task_update accept and validate sandbox; hot-reload diffing includes it. +23 tests (pytest 958 → 981, Agent.md synced).
… fix)
ntpath.isabs('/etc/hosts') returns False (rooted-relative, no drive), so
the workspace-write check treated out-of-workspace absolute targets as
in-workspace relative ones on Windows. _is_absolute_path now also
classifies '/...' and '\...' as absolute (review #886 test-windows ❌).argszero
commented
Aug 20, 2026
argszero
left a comment
OwnerAuthor
There was a problem hiding this comment.
✅ LGTM — cycle (full suite 980 passed + 1 skipped locally; test + test-windows CI green after the Windows drive-less-root fix)
argszero
commented
Aug 20, 2026
argszero
left a comment
OwnerAuthor
There was a problem hiding this comment.
✅ LGTM — cycle 2 (independent re-review: sandbox tiers, static check, honest partial/full enforcement, task wiring all match the design; CI test + test-windows green)
argszero
commented
Aug 20, 2026
argszero
left a comment
OwnerAuthor
There was a problem hiding this comment.
✅ LGTM — cycle 3 (head unchanged since cycle 2, CLEAN/MERGEABLE, CI green) — merging
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 freeto 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.
Implement file-level isolation for the bash tool, per host design-finalized rant 2026-08-20T15:46:50 (learned from DeepSeek Harness's sandbox modes).
Design (EMRG-minimal, per host spec)
Three per-task sandbox tiers, default = danger-full-access (current behavior, zero breakage):
rm -r/-rf/-R,rmdir,mv,cp -r, and shell redirects (> / >> / 2> / &>) to any non-/dev/null target~/.emrg/config.toml,emrgd.token,tasks.yml,projects.yml,rants.jsonl), to~/.emrgitself, and to absolute paths outside the workspace root (OS temp dir allowed — mirrors dsh's workspace + backend-promised temp area)Enforcement is honestly reported: checked modes report
partial(static heuristic scan — no bwrap/Seatbelt/ACL, per host's explicit no-heavy-dependency decision); danger-full-access reportsfull. Blocked commands return a⛔ [sandbox:...] ... not executedToolResult; successful sandboxed runs tag output with[sandbox:<mode> enforcement=partial] ok.Wiring
TaskRequest.sandboxfield (protocol) → daemon tool loop injects it into bash tool args (the agent cannot choose its own sandbox — config decides)sandbox:field in tasks.yml wins; builtin defaults —emrg-task→workspace-write,*-opensource-task→read-only, custom tasks → full access; upgrade sessions runworkspace-writetask_create/task_updateaccept and validate the sandbox field; hot-reload diff signature includes itAcceptance (from the rant)