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
- Strip or replace '/' and '\\' from the name before validation (generateDefaultSkillNameFromUrl should sanitize URL segments first).
- Let the generator derive the name (toKebabCase) instead of passing raw user input.
- 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
- Never pass raw URL paths or user input directly as skill names.
- Sanitize separators (to '-') before validation.
- Treat skill names as filesystem identifiers: whitelist-allowed characters only.
- Sanitize at the boundary where URL-derived segments are created.
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
- Skill name cannot consist only of dots
- Refusing to trust ${configName}: it resolves outside the clo
- Invalid branch or ref name. Name must not start with '-': ${
- Refusing to trust ${configName}: the remote repository's con
- Remote config not trusted
AI-assisted analysis of yamadashy/repomix@f465ad9093 (2026-08-29).
Data as JSON: /api/errors/694f38506197b394.
Report an issue: GitHub.