Skip to content

guardrails/source-control: worktree-create.sh drive-relative C:foo root bypasses containment guard (fail-open, Windows) #962

Description

@kyle-sexton

Problem

worktree-create.sh's containment guard is bypassed by a Windows drive-relative root of the form C:foo (a drive letter + path with NO separator after the colon). Git-for-Windows resolves C:foo against that drive's per-drive current directory to <toplevel>/foo, landing the worktree checkout INSIDE the repository — while the containment ancestor-walk is skipped (parent==probe on a separatorless string, so the [[ -e ]] probe is false and the guard block never runs). Fail-open.

Repro

bash worktree-create.sh --name feat/x --root 'C:foo' --repo-dir "$repo" from a shell whose C: drive CWD is inside $repo → exit 0, checkout at <toplevel>/foo.

Scope / why this is a SEPARATE follow-up (not a #898 regression)

Confirmed by independent verification of PR #898 (backslash-root fix, head 1ff6d69):

Deferred under the #650 model (repro + fix direction + origin cite), permitted because it fails on a pathological non-default input, not because it's a merge-gate/security-posture fail-open on the default path.

Fix direction

Handle drive-relative C:x input in the anchor/normalize stage: detect a drive-letter prefix NOT followed by a separator, and either reject (fail closed) or canonicalize it to absolute (e.g. via cygpath -m/-w resolving the drive CWD) BEFORE the append + normalize_path + ancestor walk, so the guard and git worktree add see the same absolute form. The anchor test (?:*) and the walk both need to treat C:x as drive-relative, not absolute.

Origin

Independent verifier of PR #898 (tower out-of-loop review, 2026-07-22 ~06:40Z), flagged for-awareness as a non-blocker.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: securitySecurity-relevant: vulnerability, hardening, or disclosure follow-up.needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.priority: mediumReal value, no hard deadline; normal backlog flow.status: readyTriaged, unblocked, and fully specified; eligible to pick up.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions