chatboxai/chatbox · error · Error
Invalid script name: path traversal not allowed
Error message
Invalid script name: path traversal not allowed
What it means
Thrown by the skills:execute-script IPC handler when scriptName contains '..', '/', or '\\'. Mirror of the skillName guard (104), this prevents the script filename segment from escaping the scripts/ subdirectory. Together with 104 and the realpath containment check (107), it forms the layered defense against arbitrary file execution.
Source
Thrown at src/main/skills/ipc-handlers.ts:182
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)
return await new Promise((resolve) => {
const TIMEOUT_MS = 30_000
let stdout = ''View on GitHub (pinned to 81571269ad)
Solutions
- Keep all executable scripts directly under skills/{name}/scripts/ with flat filenames.
- Validate scriptName in the renderer with the same strict allowlist as skillName.
- If subdirectories are required, enumerate scripts at install time and pass an index, not a path.
Example fix
// before
if (scriptName.includes('..') || scriptName.includes('/') || scriptName.includes('\\')) {
throw new Error('Invalid script name: path traversal not allowed')
}
// after — reuse a shared strict identifier validator
const SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/
if (!SAFE_NAME.test(scriptName)) {
throw new Error(`Invalid script name: ${scriptName}`)
} Defensive patterns
Strategy: validation
Validate before calling
const SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/
function isSafeScriptName(name: string): boolean {
return SAFE_NAME.test(name)
}
if (!isSafeScriptName(scriptName)) {
throw new Error(`Invalid script name: ${scriptName}`)
} 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
const result = await ipcRenderer.invoke('skills:execute-script', params)
if (!result.success && /path traversal/i.test(result.stderr)) {
showToast('Script name contains invalid characters')
} Prevention
- Keep scripts flat under scripts/ — no subdirectories in scriptName.
- Validate scriptName with the same strict allowlist as skillName.
- When listing scripts for the UI, filter out anything failing the allowlist so it can never be selected.
When it happens
Trigger: An IPC payload sets scriptName to '../foo.sh', 'subdir/run.sh', or '..\\evil.bat'. path.join(skillsDir, skillName, 'scripts', scriptName) would resolve these to a path outside the intended scripts directory.
Common situations: A skill organizes scripts in subdirectories and the caller passes a relative path; a malicious payload attempts to execute a sibling file; buggy construction of scriptName from a UI list that includes directory prefixes.
Related errors
- Invalid skill 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/bf57e6fd4efd7bd0.
Report an issue: GitHub.