MCPcopy
hub / github.com/colbymchenry/codegraph / validatePathWithinRoot

Function validatePathWithinRoot

src/utils.ts:110–146  ·  view source on GitHub ↗
(
  projectRoot: string,
  filePath: string,
  options?: { allowSymlinkEscape?: boolean }
)

Source from the content-addressed store, hash-verified

108 * escapes the root
109 */
110export function validatePathWithinRoot(
111 projectRoot: string,
112 filePath: string,
113 options?: { allowSymlinkEscape?: boolean }
114): string | null {
115 const resolved = path.resolve(projectRoot, filePath);
116 const normalizedRoot = path.resolve(projectRoot);
117
118 // 1. Lexical containment — cheap, catches `../` traversal. Applies even on
119 // the indexing read path: a crafted `../` escape is still rejected.
120 if (!isWithinDir(resolved, normalizedRoot)) {
121 return null;
122 }
123
124 // 2. Symlink-aware containment — resolve symlinks on both sides and re-check,
125 // so an in-repo symlink whose real target escapes the root is rejected.
126 // The indexing read path (allowSymlinkEscape) skips only this rejection so
127 // it stays consistent with the directory walk, which already followed the
128 // in-root symlink to enumerate these files (#935).
129 try {
130 const realRoot = fs.realpathSync(normalizedRoot);
131 const realResolved = fs.realpathSync(resolved);
132 if (options?.allowSymlinkEscape) {
133 return realResolved;
134 }
135 return isWithinDir(realResolved, realRoot) ? realResolved : null;
136 } catch (err) {
137 // ENOENT: the path doesn't exist yet (a file about to be written, or an
138 // index entry for a since-deleted file) — no symlink to follow, and the
139 // lexical check already passed, so allow the lexical path. Any other
140 // resolution failure (ELOOP, EACCES, …) is treated as unsafe → reject.
141 if ((err as NodeJS.ErrnoException).code === 'ENOENT') {
142 return resolved;
143 }
144 return null;
145 }
146}
147
148/**
149 * Validate that a path is a safe project root directory.

Callers 9

buildDetectionContextMethod · 0.90
indexAllMethod · 0.90
indexFileMethod · 0.90
indexFileWithContentMethod · 0.90
extractNodeCodeMethod · 0.90
handleExploreMethod · 0.90
handleFileViewMethod · 0.90
security.test.tsFile · 0.90

Calls 2

isWithinDirFunction · 0.85
resolveMethod · 0.80

Tested by

no test coverage detected