ensureWorktreePathSafe validates a --worktree target before we write to it: it must be a non-existent path (git will create it) or an existing directory, and never a symlink at its final component. A symlinked ancestor (e.g. macOS tmp -> /private/tmp) is fine; os.Lstat checks only the leaf so it is
(path string)
| 438 | // followed. Rejecting a leaf symlink guards against writing PR content through a |
| 439 | // planted link. |
| 440 | func ensureWorktreePathSafe(path string) error { |
| 441 | fi, err := os.Lstat(path) |
| 442 | switch { |
| 443 | case os.IsNotExist(err): |
| 444 | return nil |
| 445 | case err != nil: |
| 446 | return err |
| 447 | case fi.Mode()&os.ModeSymlink != 0: |
| 448 | return fmt.Errorf("--worktree path must not be a symlink: %s", path) |
| 449 | case !fi.IsDir(): |
| 450 | return fmt.Errorf("--worktree path must be a directory: %s", path) |
| 451 | } |
| 452 | return nil |
| 453 | } |
| 454 | |
| 455 | func executeCmds(client *git.Client, credentialPattern git.CredentialPattern, cmdQueue [][]string) error { |
| 456 | for _, args := range cmdQueue { |