19c3771cf0
* fix: validate destination parent chain in copyfiles byte copy copyState.copyFile wrote into the target worktree via os.MkdirAll + os.Create with no destination-parent symlink validation, unlike the sibling paths that were hardened for exactly this: symlinkMatch calls validateParentChain and remote writeOneEntry calls secureDestination. A worktree whose HEAD ships a directory segment as a symlink (a fork-PR head can set a tree entry to mode 120000 pointing at an absolute host path) let MkdirAll follow the link and os.Create write the source file's bytes outside the worktree as the backend user — a zero-click, content-driven arbitrary-file-write reachable on the PR-review path (copyConfiguredFiles -> copyfiles.Copy during worktree creation). Route the byte copy through the same secureDestination hardening: it runs validateParentChain, creates the parent dirs, and re-confirms containment via EvalSymlinks before returning a destination guaranteed inside the worktree. A rejected destination emits a non-fatal warning, mirroring symlinkMatch. The leaf os.Lstat skip-if-exists behavior is preserved (only a symlinked parent was the escape vector). Add byte-copy regression tests: a symlinked parent is rejected and nothing is written outside the worktree, a leaf symlink is still skipped, and a clean nested copy still works. * fix: canonicalize copyfiles target root before containment checks copyFile passed the raw s.targetDir into secureDestination, which EvalSymlinks-resolves the created parent and then Rel-checks it against that root. When the worktree is reached through a symlinked ancestor (macOS /tmp -> /private/tmp, or a user-symlinked tasks dir) the canonical parent looks like it escapes the non-canonical root, so every legitimate byte copy is silently rejected. Resolve targetDir once in Copy (falling back to the raw path when it does not exist yet), mirroring the EvalSymlinks WriteEntries already performs. Add a regression test that routes the target through a symlinked ancestor and asserts the copy still lands at the real location. --------- Co-authored-by: Kandev Agent <agent@kandev.dev>