Skip to content

Add worktree + chmod sandbox mode#42

Merged
mrjf merged 2 commits into
mainfrom
feat/worktree-chmod-sandbox
May 17, 2026
Merged

Add worktree + chmod sandbox mode#42
mrjf merged 2 commits into
mainfrom
feat/worktree-chmod-sandbox

Conversation

@mrjf
Copy link
Copy Markdown
Owner

@mrjf mrjf commented May 16, 2026

Summary

Alternative to bwrap mount-namespace isolation for file access control. Uses git sparse-checkout worktrees and POSIX file permissions instead of Linux namespace bind-mounts.

How it works

  1. Sparse-checkout worktree — only files matching allow.read/allow.write patterns are materialized on disk
  2. chmod -R 000 — deny everything in the worktree
  3. chmod a+x on traversal directories (navigate but NOT list — prevents directory enumeration)
  4. chmod a+r on allow.read files
  5. chmod a+rw on allow.write files
  6. chmod 000 on deny.read/deny.write files (deny overrides allow)
  7. Script runs as band-runner (unprivileged) — kernel enforces permissions
  8. Worktree torn down after execution

Advantages over bwrap

  • Works on systems without bubblewrap (macOS, some containers)
  • Simpler to debug (ls -la shows permissions)
  • Git-native: sparse checkout means only relevant files exist
  • Same security guarantees (kernel-level enforcement)

New files

  • packages/runtime/src/worktree-chmod.ts — pure functions: plan generation, chmod script building, sparse-checkout patterns, symlink filtering, path safety validation, shell quoting
  • packages/runtime/test/unit/worktree-chmod.test.ts — 45 unit tests covering security invariants

Integration

  • band-server.ts gains sandboxMode: "bwrap" | "worktree-chmod" in ExecRequest
  • ExecutionConfig.lima gains optional sandboxMode field
  • Default remains "bwrap" — worktree-chmod is opt-in via band config

Test plan

  • 45 unit tests for worktree-chmod module (plan generation, script ordering, security invariants)
  • All existing tests pass (545 total across format + editor + runtime)
  • Integration test with Lima VM (requires sandboxMode: "worktree-chmod" in BAND.md + git repo in VM)

🤖 Generated with Claude Code

Alternative to bwrap mount-namespace isolation. Uses git sparse-checkout
worktrees and POSIX file permissions to enforce allow/deny rules:

1. Create sparse-checkout worktree (only allowed paths materialized)
2. chmod -R 000 (deny everything)
3. chmod a+x on traversal dirs (navigate but not list)
4. chmod a+r on allow.read files
5. chmod a+rw on allow.write files
6. chmod 000 on deny.read/deny.write (override allow)
7. Run script as band-runner (unprivileged)
8. Tear down worktree

New files:
- packages/runtime/src/worktree-chmod.ts — pure functions for plan
  generation, script building, sparse-checkout patterns, symlink
  filtering, path safety validation
- packages/runtime/test/unit/worktree-chmod.test.ts — 45 tests
  covering traversal computation, chmod plan generation, script
  ordering, shell injection prevention, security invariants

Integration:
- band-server.ts gains sandboxMode: "bwrap" | "worktree-chmod"
  in ExecRequest, dispatching to the appropriate sandbox
- ExecutionConfig.lima gains sandboxMode field
- Default remains "bwrap" — worktree-chmod is opt-in

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mrjf
Copy link
Copy Markdown
Owner Author

mrjf commented May 16, 2026

@copilot

chmod a+rw on allow.write files

can't we ONLY have write, and not read? i don't think write needs to imply read.

Copy link
Copy Markdown
Contributor

Copilot AI commented May 16, 2026

@copilot

chmod a+rw on allow.write files
...

Changed this in 204f281: allow.write now grants a+w only, so write-only files no longer implicitly become readable. Files that are in both allow.read and allow.write still end up with both permissions via the separate read + write phases.

Copilot finished work on behalf of mrjf May 16, 2026 19:15
@mrjf mrjf enabled auto-merge May 17, 2026 00:39
@mrjf mrjf merged commit bc64465 into main May 17, 2026
3 checks passed
@mrjf mrjf deleted the feat/worktree-chmod-sandbox branch May 17, 2026 00:39
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.

2 participants