Skip to content

Fix git worktree object database in VM snapshots#94

Merged
jhrozek merged 1 commit intomainfrom
fix/worktree-objects
Apr 8, 2026
Merged

Fix git worktree object database in VM snapshots#94
jhrozek merged 1 commit intomainfrom
fix/worktree-objects

Conversation

@jhrozek
Copy link
Copy Markdown
Contributor

@jhrozek jhrozek commented Mar 27, 2026

Summary

When a workspace is a git worktree, the object database lives in the main repository's .git/objects/ — outside the workspace and not included in the snapshot. This causes git inside the VM to show "No commits yet" with all files appearing untracked.

Fixes #49

Approach

Mount the main repo's .git/objects/ as a read-only virtiofs share and reconstruct a proper .git/ directory in the snapshot that references it via objects/info/alternates.

Domain layer

  • Extend SnapshotPostProcessor to return PostProcessResult with optional mount requests and diff-exclude patterns
  • Add ExtraMounts field to VMConfig

Infrastructure

  • Add WorktreeProcessor that detects worktrees, reconstructs .git/ in the snapshot with objects/info/alternates pointing to the guest mount, and returns mount + exclude requests
  • Add InjectMountConfig rootfs hook writing /etc/broodbox-mounts.json
  • Wire extra virtiofs mounts in VM runner

Guest

  • Add mountExtras in bbox-init reading the mount config and mounting additional virtiofs shares between boot and seccomp hardening

Application

  • Collect post-processor results in sandbox orchestrator, wire mounts into VMConfig, compose diff matcher with extra excludes

Security hardening

  • Path traversal prevention: Validates gitdir path contains /.git/worktrees/ before proceeding; rejects symlinks via os.Lstat in file copy
  • Defense-in-depth: Verifies resolved git directory contains HEAD before treating it as a git repo
  • Config sanitization: Credentials stripped from .git/config via existing SanitizeConfig()
  • Host path not exposed: Guest mount config JSON excludes HostPath — guest only sees tag, mount point, and read-only flag

Trade-off

Agent file changes persist through normal flush+review but git commits do not persist (the reconstructed .git is excluded from diff). This avoids the complexity of mapping reconstructed git state back to the original worktree structure.

Known limitation: Host-side virtiofs mount has no read-only enforcement (go-microvm's VirtioFSMount lacks a ReadOnly field). Read-only is enforced guest-side via MS_RDONLY + seccomp blocking mount/umount syscalls.

Test plan

  • TestWorktreeProcessor_ExternalWorktree — full reconstruction verified
  • TestWorktreeProcessor_DetachedHEAD — raw SHA HEAD preserved
  • TestWorktreeProcessor_CraftedGitdir — path traversal rejected
  • TestWorktreeProcessor_SymlinkInGitdir — symlink not followed
  • TestWorktreeProcessor_ConfigIsSanitized — credentials stripped
  • TestWorktreeProcessor_NotAWorktree / NoGitEntry / MalformedGitFile / MissingObjects — graceful no-ops
  • TestComposeMatcher — prefix matching verified, no false positives on .github/.gitignore
  • task lint — 0 issues
  • Manual: bbox claude-code in a git worktree → git log shows history

🤖 Generated with Claude Code

@jhrozek
Copy link
Copy Markdown
Contributor Author

jhrozek commented Mar 27, 2026

Draft,because I haven't had time to test this properly but this is what I used to run bbox in worktrees

@jhrozek jhrozek force-pushed the fix/worktree-objects branch from 3ca0437 to 5839741 Compare March 27, 2026 14:40
When a workspace is a git worktree, the object database lives in
the main repository's .git/objects/ — outside the workspace and
not included in the snapshot. This causes git inside the VM to
show "No commits yet" with all files appearing untracked.

Fix by detecting worktrees during snapshot post-processing,
reconstructing a proper .git/ directory with objects/info/alternates,
and mounting the main repo's objects directory as a read-only
virtiofs share inside the VM.

Agent file changes persist through normal flush+review but git
commits do not (the reconstructed .git is excluded from diff).

Security hardening from review:
- Validate commondir resolves to an ancestor of gitdirPath
- Reject symlinked root directories in copyDirRecursive
- Propagate ReadOnly flag to host-side virtiofs mount
- Delegate config sanitization to ConfigSanitizer (SRP)

Fixes #49

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jhrozek jhrozek force-pushed the fix/worktree-objects branch from 5839741 to 6181694 Compare April 8, 2026 11:25
@jhrozek jhrozek marked this pull request as ready for review April 8, 2026 11:26
@jhrozek
Copy link
Copy Markdown
Contributor Author

jhrozek commented Apr 8, 2026

no longe a draft

@jhrozek jhrozek merged commit 57ce5eb into main Apr 8, 2026
8 checks passed
@jhrozek jhrozek deleted the fix/worktree-objects branch April 8, 2026 22: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.

Worktree snapshots lack object database — git shows "No commits yet"

2 participants