yamadashy/repomix · error

Skill name cannot contain path separators or null bytes

Error message

Skill name cannot contain path separators or null bytes

What it means

validateSkillName rejects skill names containing '/', '\\', or null bytes before the name is used to build a skill directory path, preventing path traversal (e.g. '../../etc'). It throws a plain Error because the input is attacker- or user-controlled and must never reach the filesystem.

Source

Thrown at src/core/skill/skillUtils.ts:29

export const toKebabCase = (str: string): string => {
  return str
    .replace(/([a-z])([A-Z])/g, '$1-$2') // Handle PascalCase/camelCase
    .replace(/[\s_]+/g, '-') // Replace spaces and underscores with hyphens
    .replace(/[^a-z0-9-]/gi, '') // Remove invalid characters
    .toLowerCase()
    .replace(/-+/g, '-') // Collapse multiple hyphens
    .replace(/^-|-$/g, ''); // Trim leading/trailing hyphens
};

/**
 * Validates and normalizes a skill name.
 * Converts to kebab-case and truncates to 64 characters.
 * Also rejects path traversal attempts.
 */
export const validateSkillName = (name: string): string => {
  // Reject path separators and null bytes to prevent path traversal
  if (name.includes('/') || name.includes('\\') || name.includes('\0')) {
    throw new Error('Skill name cannot contain path separators or null bytes');
  }

  // Reject dot-only names (., .., ...)
  if (/^\.+$/.test(name)) {
    throw new Error('Skill name cannot consist only of dots');
  }

  const kebabName = toKebabCase(name);

  if (kebabName.length === 0) {
    throw new Error('Skill name cannot be empty after normalization');
  }

  return kebabName.substring(0, SKILL_NAME_MAX_LENGTH);
};

/**
 * Converts a string to Title Case.

View on GitHub (pinned to f465ad9093)

Solutions

  1. Strip or replace '/' and '\\' from the name before validation (generateDefaultSkillNameFromUrl should sanitize URL segments first).
  2. Let the generator derive the name (toKebabCase) instead of passing raw user input.
  3. If intentional, encode separators (e.g. 'my-skill') manually.

Example fix

// before
const name = validateSkillName(url.pathname); // may contain '/'
// after
const name = validateSkillName(url.pathname.replaceAll('/', '-'));
Defensive patterns

Strategy: validation

Validate before calling

export const sanitizeSkillNameInput = (raw: string): string =>
  raw.replaceAll(/[\\/\0]/g, '-');
const name = validateSkillName(sanitizeSkillNameInput(input));

Type guard

const isSafeSkillName = (s: string): boolean =>
  !s.includes('/') && !s.includes('\\') && !s.includes('\0');

Try / catch

try {
  const name = validateSkillName(input);
} catch (e) {
  if (e.message.includes('path separators or null bytes')) {
    const name = validateSkillName(input.replaceAll(/[\\/\0]/g, '-'));
  } else throw e;
}

Prevention

When it happens

Trigger: Calling validateSkillName (via generateDefaultSkillName or generateDefaultSkillNameFromUrl) with a name containing a path separator or NUL — e.g. deriving a skill name from a URL path segment that still contains slashes, or raw user input passed through unmodified.

Common situations: Auto-deriving a skill name from a GitHub URL whose path segments weren't fully sanitized; users typing names like 'my/skill' in prompts; interpolating untrusted input into skill names in scripts.

Related errors


AI-assisted analysis of yamadashy/repomix@f465ad9093 (2026-08-29). Data as JSON: /api/errors/694f38506197b394. Report an issue: GitHub.