{"record":{"id":"552ce006d43c94f2","repo":"mastra-ai/mastra","slug":"invalid-file-path-filepath-path-traversal-is-552ce0","errorCode":null,"errorMessage":"Invalid file path \"${filePath}\". Path traversal is not allowed.","messagePattern":"Invalid file path \"(.+?)\"\\. Path traversal is not allowed\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"packages/server/src/server/handlers/workspace.ts","lineNumber":1314,"sourceCode":"  return name;\n}\n\n/**\n * Validate that a file path is safe (no traversal, no absolute paths).\n * Prevents malicious API responses from writing files outside the skill directory.\n */\nfunction assertSafeFilePath(filePath: string): string {\n  // Reject absolute paths\n  if (filePath.startsWith('/') || /^[a-zA-Z]:/.test(filePath)) {\n    throw new HTTPException(400, {\n      message: `Invalid file path \"${filePath}\". Absolute paths are not allowed.`,\n    });\n  }\n  // Reject path traversal attempts\n  const segments = filePath.split('/');\n  for (const segment of segments) {\n    if (segment === '..' || segment === '.') {\n      throw new HTTPException(400, {\n        message: `Invalid file path \"${filePath}\". Path traversal is not allowed.`,\n      });\n    }\n  }\n  return filePath;\n}\n\ninterface SkillFileEntry {\n  path: string;\n  content: string;\n  encoding: 'utf-8' | 'base64';\n}\n\ninterface SkillFilesResponse {\n  skillId: string;\n  owner: string;\n  repo: string;\n  branch: string;","sourceCodeStart":1296,"sourceCodeEnd":1332,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/workspace.ts#L1296-L1332","documentation":"Thrown by assertSafeFilePath when any '/'-separated segment of the skill file path is '..' or '.', indicating path traversal. This prevents escaping the skill directory via segments like '../../etc/passwd'. It is an HTTPException with status 400.","triggerScenarios":"Requesting a skill file with a path containing '..' or '.' segments, e.g. 'foo/../../secret.txt' or './SKILL.md', against the workspace skills endpoint.","commonSituations":"Users constructing paths by string concatenation with user input; directory-style navigation assumptions ('.' for current dir); malicious payloads probing for traversal vulnerabilities.","solutions":["Remove '.' and '..' segments by resolving and re-relativizing the path before sending it (e.g. path.posix.normalize, then verify it does not start with '..').","Send canonical paths exactly as returned by the Skills API file listing.","Sanitize or reject paths containing traversal segments in your own service before proxying to this endpoint."],"exampleFix":"// before\nconst p = `${base}/../${name}`;\nawait installSkill({ workspaceId, filePath: p });\n// after\nconst p = path.posix.normalize(path.posix.join(base, name));\nif (p.split('/').includes('..')) throw new Error('traversal');\nawait installSkill({ workspaceId, filePath: p });","handlingStrategy":"validation","validationCode":"function hasNoTraversal(p) {\n  return !p.split('/').some(s => s === '..' || s === '.');\n}\nif (!hasNoTraversal(filePath)) throw new Error('Path contains traversal segments');","typeGuard":"function isTraversalFree(p: unknown): p is string {\n  return typeof p === 'string' && !p.split('/').some(seg => seg === '..' || seg === '.');\n}","tryCatchPattern":"try {\n  await installSkill({ workspaceId, filePath });\n} catch (e) {\n  if (String(e.message).includes('Path traversal is not allowed')) {\n    throw new Error(`Refusing unsafe path: ${filePath}. Use a canonical path from the skill listing.`);\n  }\n  throw e;\n}","preventionTips":["Canonicalize paths (resolve then re-relativize) before sending; drop '..' and '.' segments.","Use the exact file paths returned by the Skills API files listing.","Add a client-side lint/test that rejects any request path containing '..' or '.' segments."],"tags":["path-traversal","security","http-400","workspace"],"backgroundTag":"path-traversal-attempt","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}