{"record":{"id":"1d780973d7fdbe93","repo":"vercel/ai","slug":"invalid-skill-file-path-for-skillname-filepa","errorCode":null,"errorMessage":"Invalid skill file path for ${skillName}: ${filePath}","messagePattern":"Invalid skill file path for (.+?): (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/harness/src/utils/write-skills.ts","lineNumber":511,"sourceCode":"  skillName?: string;\n  filePath: string;\n  mode: SkillFilePathMode;\n  message?: (input: { skillName: string; filePath: string }) => string;\n}): string {\n  const normalized =\n    mode === 'strip-leading-slashes'\n      ? filePath.replace(/^\\/+/, '')\n      : path.posix.normalize(filePath);\n  const invalid =\n    normalized === '' ||\n    (mode === 'relative' && normalized === '.') ||\n    normalized.startsWith('../') ||\n    normalized.includes('/../') ||\n    normalized.endsWith('/..') ||\n    (mode === 'relative' && path.posix.isAbsolute(normalized));\n\n  if (invalid) {\n    throw new Error(\n      message?.({ skillName: skillName ?? '', filePath }) ??\n        `Invalid skill file path for ${skillName}: ${filePath}`,\n    );\n  }\n  return normalized;\n}\n\nfunction renderSkillFile({\n  skill,\n  trailingNewline,\n}: {\n  skill: HarnessV1Skill;\n  trailingNewline: boolean;\n}): string {\n  const content = `---\\nname: ${skill.name}\\ndescription: ${skill.description}\\n---\\n\\n${skill.content}`;\n  return trailingNewline ? `${content}\\n` : content;\n}\n","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness/src/utils/write-skills.ts#L493-L529","documentation":"Thrown by normalizeSkillFilePath in the harness package when a skill file path fails safety validation after normalization. Paths that escape the skill directory ('..' traversal segments), are empty, are '.', or are absolute when a relative path is required are rejected. This prevents writing skill files outside the intended skill folder (path traversal).","triggerScenarios":"Calling projectSkill (or write-skills APIs) with a skill whose file path: contains '../' segments, resolves to '' or '.', starts with '/', or equals/ends with '..'. Also triggered when mode is 'relative' and the normalized path is absolute.","commonSituations":"Programmatically generated skill manifests with user-supplied paths; migrating skills from another tool that used absolute paths; accidental '..' in a path template; empty file path fields in skill YAML frontmatter.","solutions":["Remove any '..' segments, leading slashes, and empty/ '.' paths from the skill's file path so it is a plain relative path like 'reference.md' or 'scripts/run.sh'.","If the path comes from user input, sanitize it first (normalize, reject absolute and traversal segments) before passing it to the skills API.","Read the thrown message — it names the offending skillName and filePath — and correct that specific entry in the manifest."],"exampleFix":"// before\nskills: [{ name: 'my-skill', files: [{ path: '../../etc/hosts', content: '...' }] }]\n// after\nskills: [{ name: 'my-skill', files: [{ path: 'etc-notes.md', content: '...' }] }]","handlingStrategy":"validation","validationCode":"function isSafeSkillFilePath(p) {\n  const normalized = p.replace(/^\\/+/, '');\n  return (\n    normalized !== '' && normalized !== '.' &&\n    !normalized.startsWith('../') && !normalized.includes('/../') &&\n    !normalized.endsWith('/..')\n  );\n}\nif (!isSafeSkillFilePath(skillFile.path)) throw new Error(`Refusing unsafe skill path: ${skillFile.path}`);","typeGuard":null,"tryCatchPattern":"try {\n  await projectSkills({ skills });\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Invalid skill file path')) {\n    console.error(`Fix skill manifest path: ${e.message}`);\n  } else throw e;\n}","preventionTips":["Store skill file paths as plain relative paths (no leading '/', no '..') in manifests.","Validate/sanitize user-supplied paths at input boundaries with path.posix.normalize before writing skills.","Add a unit test asserting traversal paths ('../x', '/abs', '') are rejected."],"tags":["path-traversal","validation","skills"],"backgroundTag":"invalid-file-path","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}