Skip to content

fix(security): refuse git-dir outside repoRoot (closes #16) - #21

Closed
axisrow wants to merge 1 commit into
mainfrom
sec-gitdir-boundary
Closed

axisrow wants to merge 1 commit into
mainfrom
sec-gitdir-boundary

Conversation

@axisrow

@axisrow axisrow commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Closes #16. createWorktree resolved git-dir without boundary check; absolute path outside repoRoot (separate-git-dir) would write info/exclude at attacker location. Fix: realpath boundary check. Regression test: separate-git-dir outside repoRoot -> throws. worktree 17/17.

Closes #16 (MEDIUM). createWorktree resolved git rev-parse --git-dir with
path.resolve(repoRoot, rawGitDir) without a boundary check. When --git-dir
returns an absolute path outside repoRoot (separate-git-dir, crafted .git
gitfile, core.worktree), path.resolve swallows it and the info/exclude write
lands at an attacker-controlled location.

Fix: after resolve, realpath-normalize gitDir and assert it is contained within
realRepoRoot (startsWith with separator). Throw otherwise. Legit linked worktrees
(gitdir inside main .git/) pass.

Regression test: repo with --separate-git-dir pointing outside repoRoot →
createWorktreeSession throws, external exclude untouched.

Verified: worktree 17/17; full npm test 160 pass / 4 pre-existing.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@axisrow

axisrow commented Jul 20, 2026

Copy link
Copy Markdown
Owner Author

Closing — Codex review found the fix breaks legit linked worktrees (gitdir in main .git/, not in repoRoot) AND info/exclude symlinks bypass the containment. Needs a redesign anchored on git-common-dir, not repoRoot. Reopening #16.

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.

security(medium): git rev-parse --git-dir outside repoRoot → info/exclude append at attacker-chosen path

1 participant