{"record":{"id":"0db86b4542988400","repo":"yamadashy/repomix","slug":"skill-name-cannot-consist-only-of-dots","errorCode":null,"errorMessage":"Skill name cannot consist only of dots","messagePattern":"Skill name cannot consist only of dots","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/core/skill/skillUtils.ts","lineNumber":34,"sourceCode":"    .toLowerCase()\n    .replace(/-+/g, '-') // Collapse multiple hyphens\n    .replace(/^-|-$/g, ''); // Trim leading/trailing hyphens\n};\n\n/**\n * Validates and normalizes a skill name.\n * Converts to kebab-case and truncates to 64 characters.\n * Also rejects path traversal attempts.\n */\nexport const validateSkillName = (name: string): string => {\n  // Reject path separators and null bytes to prevent path traversal\n  if (name.includes('/') || name.includes('\\\\') || name.includes('\\0')) {\n    throw new Error('Skill name cannot contain path separators or null bytes');\n  }\n\n  // Reject dot-only names (., .., ...)\n  if (/^\\.+$/.test(name)) {\n    throw new Error('Skill name cannot consist only of dots');\n  }\n\n  const kebabName = toKebabCase(name);\n\n  if (kebabName.length === 0) {\n    throw new Error('Skill name cannot be empty after normalization');\n  }\n\n  return kebabName.substring(0, SKILL_NAME_MAX_LENGTH);\n};\n\n/**\n * Converts a string to Title Case.\n * Handles kebab-case, snake_case, and other separators.\n */\nconst toTitleCase = (str: string): string => {\n  return str\n    .replace(/[-_]/g, ' ')","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/yamadashy/repomix/blob/f465ad909315a22120636baf03fa5e28701a50cb/src/core/skill/skillUtils.ts#L16-L52","documentation":"validateSkillName rejects names composed solely of dots ('.', '..', '...') because such names resolve to the current or parent directory — another path-traversal/invalid-directory guard. Thrown before kebab-case conversion.","triggerScenarios":"Calling validateSkillName with '.', '..', or any all-dots string — e.g. a skill name extracted from a URL like 'https://example.com/..' or user input that is just dots.","commonSituations":"Malicious or degenerate URL inputs used to auto-generate skill names; users submitting dot-names in interactive prompts; templated scripts where a variable came out as '..'.","solutions":["Sanitize input to strip dot-only values before calling validateSkillName.","Provide a fallback default name when the derived name is empty/dots.","Fix the source (URL parsing) that produced the dot-only segment."],"exampleFix":"// before\nconst name = validateSkillName(segment);\n// after\nconst name = /^[.]+$/.test(segment) ? 'default-skill' : validateSkillName(segment);","handlingStrategy":"validation","validationCode":"const safeSegment = (s: string) => (/^[.]+$/.test(s) || s.trim() === '' ? 'default-skill' : s);\nconst name = validateSkillName(safeSegment(input));","typeGuard":"const isUsableSkillName = (s: string): boolean =>\n  s.length > 0 && !/^[.]+$/.test(s);","tryCatchPattern":"try {\n  const name = validateSkillName(input);\n} catch (e) {\n  if (e.message.includes('consist only of dots')) {\n    const name = validateSkillName('default-skill');\n  } else throw e;\n}","preventionTips":["Reject or replace dot-only inputs before generating skill names.","Sanitize URL path segments used for auto-naming.","Always provide a fallback default skill name.","Validate interactive user input at prompt time."],"tags":["security","path-traversal","validation"],"backgroundTag":"invalid-path-name","analyzedSha":"f465ad909315a22120636baf03fa5e28701a50cb","analyzedAt":"2026-08-29T01:27:42.024Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}