fix(files): harden the outside-worktree root after review

Keep the 1.49.0 API meaning: liveWorktree and root=live stay inside the
session folder, and an outside worktree is published as outsideWorktree
and walked only with root=live-any.

Refuse a symlinked .git folder as the main worktree, sensitive files
inside a followed worktree, and any outside worktree while attachment
confinement is on or around a blocked tree. The file routes re-check
the guard settings on every request, and a throwing rule check refuses.
The panel keeps its Back to worktree button while pinned to the session
folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Michael GrundbergandClaude Opus 5.5 committed 2026-11-06 20:33:14 +01:00
1 parent c9b79097b0
commit 8d33f53fd0
28 files changed
+856 -198

No files matched your search

+6 -2
View File
@@ -1639,7 +1639,9 @@ export class Session extends EventEmitter {
}
/**
* The linked git worktree that {@link paneCwd} is in, when there is one (`live-worktree.ts`).
* The git worktree that {@link paneCwd} is in, when there is one (`live-worktree.ts`): a linked
* worktree inside `workingDir`, or, for an outside answer, a linked worktree or the repository's
* main worktree (from a session started in a linked one).
* The Files panel lists it instead of the main checkout. Runtime-only, like `paneCwd`. One inside
* `workingDir` is never a confinement root: it is judged lexically when the pane moves, and the
* listing route re-checks the real folder on every request. One outside it (`outside: true`) is
@@ -2419,7 +2421,9 @@ export class Session extends EventEmitter {
status: this._status,
workingDir: this.workingDir,
paneCwd: this._paneCwd,
liveWorktree: this._liveWorktree,
// The wire keeps `liveWorktree` inside `workingDir` only; an outside answer rides its own field.
liveWorktree: this._liveWorktree?.outside ? undefined : this._liveWorktree,
outsideWorktree: this._liveWorktree?.outside ? this._liveWorktree : undefined,
remote: this._remote,
docker: this._docker,
adopt: this._adopt,