{"record":{"id":"5b5e789c125a28f1","repo":"thedotmack/claude-mem","slug":"access-denied-filepath-resolves-outside-the-workspace-root","errorCode":null,"errorMessage":"Access denied: \"${filePath}\" resolves outside the workspace (${root}). MCP file tools can only read files within the current project.","messagePattern":"Access denied: \"(.+?)\" resolves outside the workspace \\((.+?)\\)\\. MCP file tools can only read files within the current project\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/smart-file-read/workspace-path.ts","lineNumber":43,"sourceCode":"export async function resolveWithinWorkspace(\n  filePath: string,\n  workspaceCwd: string = process.cwd(),\n): Promise<string> {\n  if (typeof filePath !== 'string' || filePath.trim().length === 0) {\n    throw new Error('file_path is required');\n  }\n\n  const root = await realpath(resolve(workspaceCwd));\n  const lexicallyResolved = resolve(root, expandLeadingTilde(filePath.trim()));\n  let resolved: string;\n  try {\n    resolved = await realpath(lexicallyResolved);\n  } catch {\n    resolved = lexicallyResolved;\n  }\n\n  if (resolved !== root && !resolved.startsWith(root + sep)) {\n    throw new Error(\n      `Access denied: \"${filePath}\" resolves outside the workspace (${root}). ` +\n      'MCP file tools can only read files within the current project.',\n    );\n  }\n\n  return resolved;\n}\n","sourceCodeStart":25,"sourceCodeEnd":51,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/smart-file-read/workspace-path.ts#L25-L51","documentation":"After resolving symlinks and normalizing, resolveWithinWorkspace verifies the resolved path is the workspace root itself or lies beneath it (resolved === root or starts with root + sep). It throws this access-denied error otherwise, enforcing that MCP file tools only read files inside the current project.","triggerScenarios":"A read is requested for an absolute path outside the workspace (/etc/passwd), a '../' traversal escaping the root, or a symlink inside the workspace pointing to an external target — the realpath resolution lands outside root.","commonSituations":"User asks the agent to read ~/.ssh/id_rsa or a sibling project; a symlinked node_modules or vendored directory points outside the repo; workspace root changed (different cwd) so previously-valid paths now escape.","solutions":["Request files with paths inside the workspace root; use relative paths from the project directory.","For files outside the workspace, change to that project directory (set workspaceCwd) or open a session rooted at the containing project.","If a legitimate file fails due to symlinks, restructure so the target is inside the workspace or copy it in.","Check that process.cwd()/workspaceCwd is the intended project root before calling."],"exampleFix":"// before\nawait resolveWithinWorkspace('/etc/passwd');\n// after\nawait resolveWithinWorkspace('src/config.ts'); // within workspace cwd","handlingStrategy":"validation","validationCode":"const root = resolve(process.cwd());\nconst resolved = resolve(root, inputPath);\nif (resolved !== root && !resolved.startsWith(root + sep)) {\n  throw new Error('path escapes workspace: ' + inputPath);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const resolved = await resolveWithinWorkspace(userPath);\n} catch (err) {\n  if (String(err).includes('resolves outside the workspace')) {\n    return mcpError(403, 'Only files inside the current project can be read.');\n  }\n  throw err;\n}","preventionTips":["Use relative paths from the workspace root in tool calls.","Reject '..' segments and absolute paths in client input.","Watch for symlinks pointing outside the repo.","Open sessions with cwd set to the project you need to read."],"tags":["security","path","sandbox","mcp"],"backgroundTag":"path-traversal-blocked","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}