fix(sandbox): stop a stale path grant from breaking bash_exec entirely#117
Merged
Conversation
An always-scoped filesystem grant can outlive its target (e.g. the user deletes a workspace that was granted earlier). Both sandbox backends hard-failed on that up front — validate_grants_exist() aborted EVERY sandboxed command with "Sandbox path grant does not exist: <path>", so one stale grant disabled bash_exec for the whole agent with no recovery path (observed 2026-07-05). Replace the hard fail with pruning: drop grants whose host path no longer exists (warn per pruned grant) and launch the sandbox without them. The stale path is then simply absent inside the sandbox — the same ENOENT an unsandboxed shell would hit at use time. Pruning only ever removes access, never widens it. - linux_bwrap: validate_grants_exist -> prune_missing_grants (keeps the Flatpak host-namespace probe; grant binds were already lenient *-bind-try, so bwrap itself never needed the hard gate) - macos_seatbelt: same prune; add_grant_filters now also skips a grant that vanishes between prune and profile build (TOCTOU) instead of erroring the command - tests: prune keeps live grants / drops stale ones (both backends), seatbelt profile builds without the stale path, plus an end-to-end bwrap regression run with a missing grant The agent-facing revoke tool for stale grants remains a separate follow-up (tracked in TODO).
juacker
marked this pull request as ready for review
July 23, 2026 10:01
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.
Summary
Fixes the bug where one stale filesystem grant disabled
bash_execentirely for an agent.Problem
An
always-scoped path grant can outlive its target — e.g. the user deletes a workspace directory that was granted earlier. Both sandbox backends then hard-failed up front invalidate_grants_exist(), so every sandboxed command aborted with:There is no agent-facing revoke tool, so the agent could never recover from its own stale grant (observed 2026-07-05; tracked in TODO under bugs/reliability).
Fix
Replace the hard fail with pruning: grants whose host path no longer exists are dropped from the profile (one
tracing::warn!per drop) and the sandbox launches without them. The stale path is then simply absent inside the sandbox — the same ENOENT an unsandboxed shell would hit at use time. Pruning can only ever remove access, never widen it.validate_grants_exist→prune_missing_grants, keeping the Flatpak host-namespace probe (flatpak-spawn --host test -e). Grant binds were already lenient (*-bind-try), so bwrap itself never needed the hard gate.add_grant_filtersnow also skips a grant that failscanonicalize(TOCTOU between prune and profile build) instead of erroring the command.Tests
cargo test --lib: 805 passed.cargo clippy --lib: clean.Review
3 independent reviews (Codex / Claude / Minimax), all
production_quality, zero blocker/major. Applied minor: derive stale test paths from dropped tempdirs. Accepted residual risk: the Flatpak fail-open probe branch is untested (would need to mockflatpak-spawn; behavior is fail-safe, bounded by*-bind-try).Follow-up (out of scope, tracked in TODO)
alwaysgrants can be cleaned from settings, plus a user-visible notice when a grant is pruned.