MCPcopy
hub / github.com/21st-dev/1code / assertParentInWorktree

Function assertParentInWorktree

src/main/lib/git/security/secure-fs.ts:66–170  ·  view source on GitHub ↗

* Validate that the parent directory chain stays within the worktree. * Handles the case where the target file doesn't exist yet (ENOENT). * * This function walks up the directory tree to find the first existing * ancestor and validates it. It also detects dangling symlinks by checking * if any

(
	worktreePath: string,
	fullPath: string,
)

Source from the content-addressed store, hash-verified

64 * @throws PathValidationError if any ancestor escapes the worktree
65 */
66async function assertParentInWorktree(
67 worktreePath: string,
68 fullPath: string,
69): Promise<void> {
70 const worktreeReal = await realpath(worktreePath);
71 let currentPath = dirname(fullPath);
72
73 // Walk up the directory tree until we find an existing directory
74 while (currentPath !== dirname(currentPath)) {
75 // Stop at filesystem root
76 try {
77 // First check if this path component is a symlink (even if target doesn't exist)
78 const stats = await lstat(currentPath);
79
80 if (stats.isSymbolicLink()) {
81 // This is a symlink - validate its target even if it doesn't exist
82 const linkTarget = await readlink(currentPath);
83 // Resolve the link target relative to the symlink's parent
84 const resolvedTarget = isAbsolute(linkTarget)
85 ? linkTarget
86 : resolve(dirname(currentPath), linkTarget);
87
88 // Try to get the realpath of the resolved target
89 try {
90 const targetReal = await realpath(resolvedTarget);
91 if (!isPathWithinWorktree(worktreeReal, targetReal)) {
92 throw new PathValidationError(
93 "Symlink in path resolves outside the worktree",
94 "SYMLINK_ESCAPE",
95 );
96 }
97 } catch (error) {
98 // Target doesn't exist - check if the resolved target path
99 // would be within worktree if it existed
100 if (
101 error instanceof Error &&
102 "code" in error &&
103 error.code === "ENOENT"
104 ) {
105 // For dangling symlinks, validate the target path itself
106 // We need to check if the target, when resolved, would be in worktree
107 // This is conservative: if we can't determine, fail closed
108 const targetRelative = relative(worktreeReal, resolvedTarget);
109 // Use sep-aware check to avoid false positives on "..config" dirs
110 if (
111 targetRelative === ".." ||
112 targetRelative.startsWith(`..${sep}`) ||
113 isAbsolute(targetRelative)
114 ) {
115 throw new PathValidationError(
116 "Dangling symlink points outside the worktree",
117 "SYMLINK_ESCAPE",
118 );
119 }
120 // Target would be within worktree if it existed - continue
121 return;
122 }
123 if (error instanceof PathValidationError) {

Callers 1

Calls 2

lstatFunction · 0.85
isPathWithinWorktreeFunction · 0.85

Tested by

no test coverage detected