{"record":{"id":"381a9466b5607961","repo":"mastra-ai/mastra","slug":"invalid-label-path-input","errorCode":null,"errorMessage":"Invalid ${label} path: ${input}","messagePattern":"Invalid (.+?) path: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/workspace/skills/workspace-skills.ts","lineNumber":1488,"sourceCode":"  /**\n   * Join path segments (workspace paths use forward slashes)\n   */\n  #joinPath(...segments: string[]): string {\n    return segments\n      .map((seg, i) => (i === 0 ? stripTrailingSlashes(seg) : stripLeadingAndTrailingSlashes(seg)))\n      .filter(Boolean)\n      .join('/');\n  }\n\n  /**\n   * Validate and normalize a relative path to prevent directory traversal.\n   * Throws if the path contains traversal segments (..) or is absolute.\n   */\n  #assertRelativePath(input: string, label: string): string {\n    const normalized = input.replace(/\\\\/g, '/');\n    const segments = normalized.split('/').filter(seg => Boolean(seg) && seg !== '.');\n    if (normalized.startsWith('/') || segments.some(seg => seg === '..')) {\n      throw new Error(`Invalid ${label} path: ${input}`);\n    }\n    return segments.join('/');\n  }\n\n  /**\n   * Get parent path\n   */\n  #getParentPath(path: string): string {\n    const lastSlash = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\\\'));\n    return lastSlash > 0 ? path.substring(0, lastSlash) : '/';\n  }\n}\n\n/**\n * Split a path into segments, tolerating both POSIX (`/`) and Windows (`\\`)\n * separators. Workspace-internal paths use forward slashes, but consumer-supplied\n * absolute paths (e.g. via `new Workspace({ skills: [...] })`) may use backslashes\n * on Windows.","sourceCodeStart":1470,"sourceCodeEnd":1506,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workspace/skills/workspace-skills.ts#L1470-L1506","documentation":"Thrown by #assertRelativePath when a path supplied to a workspace skill operation is absolute or contains traversal segments ('..'). It normalizes backslashes to forward slashes and rejects any path that starts with '/' or has a '..' segment, returning the cleaned segment list on success.","triggerScenarios":"Calling skill file APIs (read/write/reference/script/asset path operations) with inputs like '/etc/passwd', '../secret.txt', 'C:\\\\tmp\\\\file', or any string containing a '..' segment.","commonSituations":"Model- or user-supplied paths passed straight through to skill file tools; joining a user-controlled relative path onto a skill base dir without sanitizing; Windows-style absolute paths pasted in.","solutions":["Sanitize the input: strip leading slashes and resolve/remove '.' and '..' segments before calling","Reject absolute or traversal inputs at your app boundary (e.g. return a validation error to the caller)","Resolve paths against a known base directory and verify the result stays inside it","Use paths returned by the skills API (discovered references/scripts/assets) instead of free-form input"],"exampleFix":"// before\nawait skills.readSkillFile(skillId, userInputPath);\n// after\nconst rel = userInputPath.replace(/\\\\/g, '/').split('/').filter(s => s && s !== '.');\nif (userInputPath.startsWith('/') || rel.some(s => s === '..')) throw new Error('invalid path');\nawait skills.readSkillFile(skillId, rel.join('/'));","handlingStrategy":"validation","validationCode":"function isSafeRelativePath(p: string): boolean {\n  const norm = p.replace(/\\\\/g, '/');\n  if (norm.startsWith('/')) return false;\n  const segs = norm.split('/').filter(s => s && s !== '.');\n  return !segs.some(s => s === '..');\n}","typeGuard":"function isRelativeSkillPath(p: unknown): p is string {\n  return typeof p === 'string' && p.length > 0 && isSafeRelativePath(p);\n}","tryCatchPattern":"try {\n  await skills.readSkillFile(id, path);\n} catch (e) {\n  if (e instanceof Error && /Invalid .* path:/.test(e.message)) {\n    return { error: 'Path must be relative and cannot contain ..' };\n  }\n  throw e;\n}","preventionTips":["Normalize user/model-supplied paths before any skill file API call","Always resolve against the skill's own directory and verify containment","Never pass raw absolute paths from clients to skill APIs","Prefer file handles/IDs returned by discovery APIs over free-form strings"],"tags":["path-traversal","security","validation","skills"],"backgroundTag":"invalid-path-input","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}