-
Notifications
You must be signed in to change notification settings - Fork 18
Implement sandbox feature for macOS (based on seatbelt) #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
stippi
wants to merge
25
commits into
main
Choose a base branch
from
sandbox
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
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
- CLI and run configs now accept/persist sandbox policies, and README/docs describe the flags. - Session configs/tests carry sandbox settings, and command execution is wrapped by the new SandboxedCommandExecutor to honor policies. - Utility modules and docs were updated to reflect the new crate boundaries and sandbox scaffolding.
... already given in lib.rs before including the module.
- Added a real macOS seatbelt pipeline: SandboxedCommandExecutor now wraps restricted policies by spawning
/usr/bin/sandbox-exec with a generated SBPL derived from SessionConfig.sandbox_policy. See
crates/code_assistant/src/utils/sandboxed_executor.rs and the new policy builder in crates/sandbox/src/seatbelt.rs (+
embedded .sbpl profiles). Non-macOS hosts still fall back with a warning. - Covered the new behavior with integration
tests in crates/code_assistant/src/tests/sandbox_tests.rs, verifying read-only denial, workspace-root allowance, and
path-escape blocking. - Exposed sandbox selection end-to-end in the GPUI: a new SandboxSelector component
(crates/code_assistant/src/ui/gpui/sandbox_selector.rs) sits beside the model selector, InputArea emits SandboxChanged,
backend persists it via the new BackendEvent::ChangeSandboxPolicy, SessionManager stores it, and UI updates arrive
through UiEvent::UpdateSandboxPolicy. RootView keeps the dropdown in sync per session, and terminal/ACP backends handle
the new responses. Key wiring touches include crates/code_assistant/src/ui/backend.rs,
crates/code_assistant/src/session/manager.rs, crates/code_assistant/src/ui/gpui/{input_area.rs,root.rs,mod.rs},
crates/code_assistant/src/ui/ui_events.rs, and terminal state.
- Added SandboxContext to track canonical writable roots and reuse them across sessions; SessionInstance now owns an Arc<SandboxContext> and keeps it in sync with init_path reloads (crates/code_assistant/src/session/instance.rs:14-86, crates/sandbox/src/context.rs:1-44). SandboxAwareProjectManager registers every resolved project path with the context, so agent sessions automatically learn about additional roots as they’re opened (crates/code_assistant/src/config.rs:20-102). SessionManager threads the context through to both the wrapped project manager and the sandboxed executor (crates/code_assistant/src/session/manager.rs:273-320). Command Permissions - Introduced SandboxCommandRequest and extended the CommandExecutor trait to accept optional per-command metadata (crates/command_executor/src/lib.rs:1-64). DefaultCommandExecutor, SandboxedCommandExecutor, ACP’s terminal executor, and all mocks implement the new signature; the sandboxed executor now merges session policy, registered roots, and per-command hints before launching seatbelt, and propagates network flags via env vars (crates/command_executor/src/default_executor.rs:1-80, sandboxed_executor.rs:1-340, crates/code_assistant/src/acp/terminal_executor.rs:10-131, crates/code_assistant/src/tests/mocks.rs:1-220). Test helpers and ACP handlers now pass the extra argument (usually None) wherever execute is called (crates/code_assistant/src/tests/sandbox_tests.rs:1-90, crates/code_assistant/src/tests/mocks.rs:560-590). Tool & Explorer Integration - ExecuteCommandTool and WriteFileTool derive a sandbox request from the selected project root so every shell command and formatter run is scoped to the proper directory (crates/code_assistant/src/tools/impls/execute_command.rs:1-240, write_file.rs:1-220). fs_explorer::Explorer now canonicalizes the project root up front, resolves every user-supplied path lexically, and rejects accesses that escape the root; added the tiny path-clean dependency to handle non-existent paths safely (crates/fs_explorer/src/Cargo.toml:9-15, src/explorer.rs:1-730).
- Introduced a permissions module with a generic mediator interface plus an AcpPermissionMediator that calls ACP’s session/request_permission. It snapshots the current tool call (via the new ACPUserUI::tool_call_update) and sends permission options (“Allow this command” vs “Deny”), using tokio::task::block_in_place to drive the ACP connection synchronously so the future stays Send. - AgentComponents/Agent now accept an optional permission_handler. ACP sessions create one (using the live ACPUserUI + AgentSideConnection) and pass it through SessionManager::start_agent_for_message; other entry points pass None. Tool Context & Command Execution - Extended ToolContext with an optional permission_handler. All context construction sites (agent runner, MCP handler, tests/mocks) now populate the new field (defaulting to None outside ACP). - ExecuteCommandTool consults the handler before running a command: it packages command line + working dir into a PermissionRequest and aborts if the user denies. The sandbox request logic remains unchanged, so approved commands still run inside the configured sandbox. Supporting Changes - Added SandboxAwareProjectManager roots into SandboxContext and ensured SessionManager threads the context and permission handler when spawning agents. - Updated the ACP agent path to keep both the concrete Arc<ACPUserUI> (for permission snapshots) and the trait object Arc<dyn UserInterface> (for the session manager), and wired the mediator only when the client connection is available. - Updated docs (docs/sandbox-plan.md) to note that Phase 1 path hardening is mostly done and that the permission UX is now being implemented via ACP.
- execute_command now treats sandbox blocks as normal tool failures and only prompts when the LLM explicitly opts in. The new ask_user_approval flag on ExecuteCommandInput/schema lets the model request an escalation; after approval the tool sets SandboxCommandRequest::bypass_sandbox so the SandboxedCommandExecutor re-runs the command outside Seatbelt (crates/code_assistant/src/tools/impls/execute_command.rs:15, crates/command_executor/src/lib.rs:16, crates/command_executor/src/sandboxed_executor.rs:57). If the user denies, the tool surfaces a clear error; approvals (Allow once / Allow always) reuse the recorded decision on subsequent calls. - The ACP permission mediator now offers “Allow always” and remembers that choice per session. Selecting it toggles an atomic flag so future ask_user_approval requests for execute_command auto-grant without UI round-trips (crates/code_assistant/src/permissions/acp.rs:13). PermissionDecision gained GrantedOnce/GrantedSession variants so tools can distinguish scopes (crates/code_assistant/src/permissions/mod.rs:27). - ToolTestFixture can host mock permission mediators, and the execute_command test suite was expanded to cover the new flows (no prompt, denial, sandbox bypass) ensuring the bypass_sandbox bit and permission call counts behave as expected (crates/code_assistant/src/tests/mocks.rs:1006, crates/code_assistant/src/tools/impls/execute_command.rs:360).
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.
No description provided.