{"record":{"id":"6e4b684bdf8eaf62","repo":"vercel/ai","slug":"invalid-cline-skill-file-path-for-skillname","errorCode":null,"errorMessage":"Invalid Cline skill file path for ${skillName}: ${filePath}","messagePattern":"Invalid Cline skill file path for (.+?): (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/harness-cline/src/cline-skills.ts","lineNumber":152,"sourceCode":"}\n\nfunction normalizeSkillFilePath({\n  skillName,\n  filePath,\n}: {\n  skillName: string;\n  filePath: string;\n}): string {\n  const normalized = path.posix.normalize(filePath);\n  if (\n    normalized === '' ||\n    normalized === '.' ||\n    normalized.startsWith('../') ||\n    normalized.includes('/../') ||\n    normalized.endsWith('/..') ||\n    path.posix.isAbsolute(normalized)\n  ) {\n    throw new Error(\n      `Invalid Cline skill file path for ${skillName}: ${filePath}`,\n    );\n  }\n  return normalized;\n}\n\nfunction renderSkillInstructions({\n  skill,\n  args,\n}: {\n  skill: ProjectedClineSkill;\n  args: string | undefined;\n}): string {\n  const trimmedArgs = args?.trim();\n  const argsTag = trimmedArgs\n    ? `\\n<command-args>${trimmedArgs}</command-args>`\n    : '';\n  const description = skill.description.trim()","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-cline/src/cline-skills.ts#L134-L170","documentation":"normalizeSkillFilePath sanitizes each file path declared by a Cline skill, rejecting paths that are empty-ish ('.'), absolute, or escape the skill directory ('..', '/../', trailing '/..'). This prevents skills from referencing files outside their own directory. The thrown message includes the offending skill name and raw path.","triggerScenarios":"A skill declares a file path that is absolute (e.g. '/etc/passwd'), starts with '../', contains '/../' in the middle, ends with '/..', or equals '.'.","commonSituations":"Skill authors using absolute paths to reference shared assets; symlinks or relative references intended to reach a sibling skill's files; Windows-style absolute paths pasted into SKILL.md frontmatter.","solutions":["Rewrite the file path as a relative path inside the skill's own directory (no leading '/', no '..').","Copy referenced external files into the skill directory and reference them relatively.","Remove '.' or '..' entries from the skill's declared file list."],"exampleFix":"// before\nfiles: [\"/usr/share/prompts/review.md\"]\n// after\nfiles: [\"prompts/review.md\"] // file copied into the skill directory","handlingStrategy":"validation","validationCode":"function assertSafeSkillPath(p) {\n  if (!p || p === '.' || p.startsWith('/') || p.startsWith('../') || p.includes('/../') || p.endsWith('/..')) {\n    throw new Error(`unsafe skill file path: ${p}`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await projectSkills(skill);\n} catch (e) {\n  if (/Invalid Cline skill file path/.test(String(e?.message))) {\n    // fix the offending path reported in the message\n  } else throw e;\n}","preventionTips":["Only use relative paths inside the skill directory","Copy shared assets into each skill folder","Lint SKILL.md file lists for absolute or '..' paths in CI"],"tags":["harness-cline","path-validation","security","skills"],"backgroundTag":"invalid-path","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}