MCPcopy
hub / github.com/modelcontextprotocol/servers / validatePath

Function validatePath

src/filesystem/lib.ts:99–140  ·  view source on GitHub ↗
(requestedPath: string)

Source from the content-addressed store, hash-verified

97
98// Security & Validation Functions
99export async function validatePath(requestedPath: string): Promise<string> {
100 const expandedPath = expandHome(requestedPath);
101 const absolute = path.isAbsolute(expandedPath)
102 ? path.resolve(expandedPath)
103 : resolveRelativePathAgainstAllowedDirectories(expandedPath);
104
105 const normalizedRequested = normalizePath(absolute);
106
107 // Security: Check if path is within allowed directories before any file operations
108 const isAllowed = isPathWithinAllowedDirectories(normalizedRequested, allowedDirectories);
109 if (!isAllowed) {
110 throw new Error(`Access denied - path outside allowed directories: ${absolute} not in ${allowedDirectories.join(', ')}`);
111 }
112
113 // Security: Handle symlinks by checking their real path to prevent symlink attacks
114 // This prevents attackers from creating symlinks that point outside allowed directories
115 try {
116 const realPath = await fs.realpath(absolute);
117 const normalizedReal = normalizePath(realPath);
118 if (!isPathWithinAllowedDirectories(normalizedReal, allowedDirectories)) {
119 throw new Error(`Access denied - symlink target outside allowed directories: ${realPath} not in ${allowedDirectories.join(', ')}`);
120 }
121 return realPath;
122 } catch (error) {
123 // Security: For new files that don't exist yet, verify parent directory
124 // This ensures we can't create files in unauthorized locations
125 if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
126 const parentDir = path.dirname(absolute);
127 try {
128 const realParentPath = await fs.realpath(parentDir);
129 const normalizedParent = normalizePath(realParentPath);
130 if (!isPathWithinAllowedDirectories(normalizedParent, allowedDirectories)) {
131 throw new Error(`Access denied - parent directory outside allowed directories: ${realParentPath} not in ${allowedDirectories.join(', ')}`);
132 }
133 return absolute;
134 } catch {
135 throw new Error(`Parent directory does not exist: ${parentDir}`);
136 }
137 }
138 throw error;
139 }
140}
141
142
143// File Operations

Callers 5

searchFunction · 0.85
readTextFileHandlerFunction · 0.85
index.tsFile · 0.85
buildTreeFunction · 0.85
lib.test.tsFile · 0.85

Calls 4

expandHomeFunction · 0.85
normalizePathFunction · 0.85

Tested by

no test coverage detected