Dataface Tasks

Prevent cbox sandboxes from mutating host git common-dir

IDINFRA_TOOLING-PREVENT_CBOX_SANDBOXES_FROM_MUTATING_HOST_GIT_COMMON_DIR
Statuscompleted
Priorityp1
Milestonem1-ft-analytics-analyst-pilot
Ownersr-engineer-architect

Problem

Sandbox containers currently mount the host repo common .git directory writable at /workspace/.repo-git. Diagnose and fix the isolation bug so sandbox git operations cannot corrupt the host checkout while still supporting task execution or failing safely when full git writes are unavailable.

Context

The container mounting logic lives in libs/cbox/cbox/container.py. The _build_base_command method constructs Docker volume mounts for all container types (sandboxes, reviews, tests). It calls _mount_worktree_git to mount the host's git common-dir inside the container.

The read_only flag passed to _mount_worktree_git was coupled to read_only_workspace — a flag that controls whether the workspace is mounted read-only. Review containers use read_only_workspace=True (so git common-dir was also :ro). Sandbox containers use read_only_workspace=False (writable workspace needed for code changes), which inadvertently made the git common-dir writable too.

This meant sandbox containers could mutate shared git state: refs, objects, packed-refs, hooks, config — potentially corrupting the host checkout or other worktrees.

Key files: - libs/cbox/cbox/container.py:367-375 — the bug site - libs/cbox/test_container_runtime.py — container mount tests

Prior work: M1-INFRA-014 fixed worktree gitdir path isolation (container-internal paths instead of host paths) but did not address the read/write permission on the mount itself.

Possible Solutions

Option A: Always mount git common-dir read-only

Decouple the git mount's read-only flag from the workspace read-only flag. Always pass read_only=True to _mount_worktree_git. One-line change. Git write operations inside the sandbox (commit, branch create, etc.) will fail with standard git "read-only filesystem" errors.

Trade-offs: Sandboxes can't create commits directly. This is acceptable because sandbox work is pushed via the host, and the task spec explicitly allows "failing safely when full git writes are unavailable."

Option B: Read-only mount + writable overlay for worktree-specific subdir

Mount git common-dir :ro but overlay a tmpfs or named volume at the worktree-specific subdirectory (.repo-git/worktrees/<name>/) so git add/git status work. More complex, more risk.

Option C: Copy-on-write / full git clone inside container

Give the sandbox its own independent .git directory. High isolation but significant startup cost and storage overhead.

Recommended: Option A — smallest reliable fix, zero risk of host mutation, clear failure mode. Option B can be layered on later if sandbox git writes are needed.

Plan

  1. Write a failing test that asserts sandbox git common-dir is mounted :ro (TDD)
  2. Change _build_base_command to always pass read_only=True to _mount_worktree_git
  3. Update existing test that expected writable mount to expect :ro
  4. Run full test suite to confirm no regressions

Files modified: - libs/cbox/cbox/container.py — one-line fix at the _mount_worktree_git call site - libs/cbox/test_container_runtime.py — new regression test + updated existing assertion

Implementation Progress

Fix applied (one-line change)

In _build_base_command, changed:

read_only=read_only_workspace,

to:

read_only=True,

This ensures the git common-dir volume mount always gets the :ro suffix, regardless of whether the workspace itself is writable.

Tests

  • New test test_sandbox_mounts_git_common_dir_read_only: creates a mock worktree, builds a sandbox command with read_only_workspace=False, and asserts the .repo-git mount ends with :ro.
  • Updated test_worktree_mount_uses_container_internal_paths: assertion updated from :/workspace/.repo-git to :/workspace/.repo-git:ro.
  • All 27 container runtime tests pass.
  • All 2604 main project tests pass (76 skipped, 3 xfailed).
  • Pre-existing failures in test_default_parent_branch.py and test_sandbox_start.py are unrelated (fail on main too).

Review Feedback

  • [ ] Review cleared