Skip to content

feat(sandbox): replace hard denies with permission-gated RequiresApproval#83

Merged
yishuiliunian merged 1 commit intomainfrom
feat/sandbox-requires-approval
Apr 5, 2026
Merged

feat(sandbox): replace hard denies with permission-gated RequiresApproval#83
yishuiliunian merged 1 commit intomainfrom
feat/sandbox-requires-approval

Conversation

@yishuiliunian
Copy link
Copy Markdown
Contributor

Summary

  • Sandbox path violations (writes outside cwd, deny_write_globs, deny_read_globs) now flow through the permission system instead of hard-blocking. Bypass auto-allows, Supervised asks the user, Auto asks the classifier.
  • PathDecision simplified from four variants (Allow/DenyWrite/DenyRead/RequiresApproval) to clean three-state model: Allow / Deny / RequiresApproval.
  • Session-scoped approval caching via ApprovedPaths ensures each path is only prompted once per session.

Changes

Layer Files What
Types loopal-config/sandbox.rs, loopal-error/io_error.rs PathDecision::Deny + RequiresApproval, ToolIoError::RequiresApproval
Sandbox loopal-sandbox/path_checker.rs deny globs + outside-cwd → RequiresApproval; ReadOnly stays Deny
Backend trait loopal-tool-api/backend.rs approve_path() + check_sandbox_path()
Backend impl loopal-backend/approved.rs (new), platform.rs (new), local.rs, path.rs ApprovedPaths with RwLock<HashSet>, resolve_checked fallback
Runtime sandbox_precheck.rs (new), tools_check.rs Path extraction + pre-check, permission elevation to Dangerous
Tests 8 new test files, 35 new tests backend, sandbox, runtime layers

Test plan

  • bazel test //... — 50 tests pass
  • bazel build //... --config=clippy — zero warnings
  • bazel build //... --config=rustfmt — clean
  • CI passes

…oval for path operations (#80)

Sandbox path violations (writes outside cwd, deny_write_globs, deny_read_globs) previously
returned hard errors that blocked operations even when the user had already approved the tool.
This prevented Loopal from performing legitimate ops tasks like editing /etc/nginx/nginx.conf.

Now these "soft denies" flow through the existing permission system:
- Bypass mode: auto-allows without prompting
- Supervised mode: asks the user with sandbox context
- Auto mode: routes to the LLM classifier

Hard denies remain for ReadOnly mode and path resolution failures (.. traversal, symlink escape).

Key changes:
- PathDecision simplified to three-state: Allow / Deny / RequiresApproval
- Backend gains approve_path() + check_sandbox_path() for session-scoped approval caching
- Runtime pre-checks extract paths from tool input before execution, elevating
  effective permission to Dangerous when sandbox approval is needed
- Execution-time fallback in resolve_checked() handles opaque tools (Bash/Glob/MCP)
- 35 new tests across backend, sandbox, and runtime layers
@yishuiliunian yishuiliunian merged commit 699e362 into main Apr 5, 2026
3 checks passed
@yishuiliunian yishuiliunian deleted the feat/sandbox-requires-approval branch April 5, 2026 08:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant