Fix project-scoped grants never matching sub-agent worktree requests - #386
Merged
TheGreatAxios merged 1 commit intoAug 8, 2026
Merged
Conversation
mintGrant stamps a project grant's cwd with the session root, but a sub-agent's request carries the cwd of its own git worktree (which can live outside the session root as a sibling directory, per CL-4929). The three sites that compared grant.cwd to request.cwd by strict equality (evaluateApprovals, isRequestCoveredByGrant, hasExactFullCommandGrant) meant a worktree path could never equal the session root, so no project-scoped grant ever matched a sub-agent request. Added a shared cwdMatchesGrant helper that resolves membership through the gate's existing rootsProvider (the authoritative registry for "which worktrees belong to this session," already used for path containment) instead of comparing raw path strings. A grant only gets this leniency when its stamped cwd matches the current gate's own session root, so a grant still never crosses project boundaries; membership within a matching project is exact equality against the resolved worktree roots, never a path-prefix.
This was referenced Aug 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mintGrantstamps a project grant'scwdwith the session root, but a sub-agent's request carries its own git-worktree cwd (which per CL-4929 can be a sibling directory of the session root, not a subdirectory). Three sites compared these by strict===, so a worktree cwd could never match a project grant — meaning project-scoped approvals never actually covered the sub-agents that generate most of the approval volume.cwdMatchesGrant(src/permission/authz-grants.ts), a single shared helper resolving membership through the gate's ownrootsProvider(the existinggit worktree list-backed registry already used for path containment) instead of comparing raw path strings. A grant only gets "one of my worktrees" leniency when its stamped cwd equals the current gate's own session root; membership within that project is exact equality against realpath-resolved roots, never a path-prefix (blocks a/repo/wt-1-evilvs/repo/wt-1spoof).evaluateApprovals,isRequestCoveredByGrant,hasExactFullCommandGrant.Security boundary note
This is a security-relevant change to grant matching. The fix does not loosen the cwd filter — it still confines a project grant to its own project. It only teaches the matcher that a sub-agent's own worktree is part of that project. Reviewed by Greybeard, Critique, gaasbot, bruckheimer, and neckbeard specifically on whether this could let a grant cross project boundaries; no leak found by any reviewer.
grantCwd !== workspace.resolvedCwdrejects any grant not belonging to the current gate's own project before roots are even consulted.Related to CL-5671 (a separate, already-ticketed bug where
classify.ts's shell auto-allow containment check is not worktree-aware, unlikepath-restriction.ts). This fix reuses the existing worktree-roots authority rather than adding a new definition of "inside the workspace"; full unification ofclassify.tswithpath-restriction.tsis scoped to CL-5671 as a separate PR.Test plan
evaluateApprovalscovering: worktree match, unrelated-project non-match (security test), session/provider-model scopes unaffected by workspacecreatePermissionGateusing a realgit worktree addsibling directory: project grant minted at session root matches a sub-agent request from the worktree; does not match a request from a genuinely unrelated directory; session-scoped grant matches regardless of cwdbun run testgreen (4084 pass, 1 pre-existing unrelated failure inlsp-availability.test.ts— checks real devDependencies presence, not touched by this change)bun run typecheckat pre-existing baseline (119 errors, none in touched files)https://linear.app/abklabs/issue/CL-5662