chatboxai/chatbox · error · Error
Invalid skill name: path traversal not allowed
Error message
Invalid skill name: path traversal not allowed
What it means
Thrown by the skills:execute-script IPC handler when skillName contains '..', '/', or '\\'. This is a path-traversal guard preventing the constructed scriptPath (path.join(skillsDir, skillName, 'scripts', scriptName)) from escaping the skills directory. It is the first of two layers — a syntactic check followed by a realpath containment check (error 107).
Source
Thrown at src/main/skills/ipc-handlers.ts:178
return { success: false, error: error instanceof Error ? error.message : 'Unknown error' }
}
})
ipcMain.handle(
'skills:execute-script',
async (
_event,
params: { skillName: string; scriptName: string; args?: string[] }
): Promise<{ success: boolean; stdout: string; stderr: string; exitCode: number | null }> => {
const { skillName, scriptName, args = [] } = params
try {
if (!skillName || !scriptName) {
throw new Error('Skill name and script name are required')
}
if (skillName.includes('..') || skillName.includes('/') || skillName.includes('\\')) {
throw new Error('Invalid skill name: path traversal not allowed')
}
if (scriptName.includes('..') || scriptName.includes('/') || scriptName.includes('\\')) {
throw new Error('Invalid script name: path traversal not allowed')
}
const skillsDir = getSkillsDir()
const scriptPath = path.join(skillsDir, skillName, 'scripts', scriptName)
if (!fs.existsSync(scriptPath)) {
throw new Error(`Script not found: ${scriptName}`)
}
const resolvedSkillsDir = fs.realpathSync(skillsDir)
const resolvedScriptPath = fs.realpathSync(scriptPath)
if (!resolvedScriptPath.startsWith(`${resolvedSkillsDir}${path.sep}`)) {
throw new Error('Script path escapes skills directory')
}
const scriptDir = path.dirname(resolvedScriptPath)View on GitHub (pinned to 81571269ad)
Solutions
- Use a flat skill identifier (alphanumeric, dash, underscore only) — never allow slashes in skill names.
- Validate skillName against a strict allowlist pattern in the renderer before invoking the IPC.
- If a nested path is genuinely needed, redesign the skill layout to be flat under skills/{name}/scripts/.
Example fix
// before
if (skillName.includes('..') || skillName.includes('/') || skillName.includes('\\')) {
throw new Error('Invalid skill name: path traversal not allowed')
}
// after — single strict allowlist regex covers traversal, slashes, and hidden dirs
const SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/
if (!SAFE_NAME.test(skillName)) {
throw new Error(`Invalid skill name: ${skillName}`)
} Defensive patterns
Strategy: validation
Validate before calling
const SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/
function isSafeSkillName(name: string): boolean {
return SAFE_NAME.test(name)
}
if (!isSafeSkillName(skillName)) {
throw new Error(`Invalid skill name: ${skillName}`)
} Type guard
function isSafeName(name: unknown): name is string {
return typeof name === 'string' && /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(name)
} Try / catch
// The handler returns { success: false, stderr: message } for all thrown errors,
// so callers check the result envelope rather than catching.
const result = await ipcRenderer.invoke('skills:execute-script', params)
if (!result.success && /path traversal/i.test(result.stderr)) {
showToast('Skill name contains invalid characters')
} Prevention
- Enforce a strict identifier allowlist (alphanumeric, dash, underscore, dot) at install time so bad names never reach disk.
- Reject skill names with slashes, backslashes, or '..' in the renderer before sending IPC.
- Treat the string check as the first layer; the realpath check (107) is the backstop.
When it happens
Trigger: A renderer (or any IPC client) sends skillName like '../', '..\\', 'a/../../../etc', or 'foo/bar'. Because path.join resolves these segments, the resulting path would point outside the skills directory without this guard.
Common situations: Malicious or buggy IPC payload; a skill whose name legitimately contains a slash is rejected (by design); testing the handler with crafted inputs. The realpath check (107) is the backstop if this string check is bypassed via symlinks.
Related errors
- Invalid script name: path traversal not allowed
- invalid file path for "${name}": ${file.path}
- Script path escapes skills directory
- Skill name and script name are required
- Script not found: ${scriptName}
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/2cfec44fbb99d211.
Report an issue: GitHub.