chatboxai/chatbox · error · Error
invalid file path for "${name}": ${file.path}
Error message
invalid file path for "${name}": ${file.path} What it means
Thrown when resolveSnapshotFilePath returns null for a file.path, i.e. the normalized path does not stay inside skillDir. resolveSnapshotFilePath resolves the target and checks target!==root && target.startsWith(root+sep) to reject path-traversal (.. segments, absolute paths) and writes outside the snapshot dir.
Source
Thrown at src/main/skills/builtin-sync.ts:180
if (normalized === '.' || lower === 'skill.md' || lower === 'source.json') return null
if (normalized.startsWith('..') || path.isAbsolute(normalized)) return null
const target = path.resolve(skillDir, normalized)
const root = path.resolve(skillDir)
if (target !== root && !target.startsWith(root + path.sep)) return null
return { target, normalizedPath: normalized.split(path.sep).join('/') }
}
function prepareSnapshotFiles(name: string, skillDir: string, files: RemoteSkillFile[]): SnapshotFileTarget[] {
const targets: SnapshotFileTarget[] = []
const seenPaths = new Set<string>()
for (const file of files) {
if (!file || typeof file.path !== 'string' || typeof file.content !== 'string') {
throw new Error(`invalid file entry for "${name}"`)
}
const resolved = resolveSnapshotFilePath(skillDir, file.path)
if (!resolved) {
throw new Error(`invalid file path for "${name}": ${file.path}`)
}
if (seenPaths.has(resolved.normalizedPath)) {
throw new Error(`duplicate file path for "${name}": ${resolved.normalizedPath}`)
}
seenPaths.add(resolved.normalizedPath)
targets.push({ file, target: resolved.target, normalizedPath: resolved.normalizedPath })
}
return targets
}
/** 将 skill 内容写入快照目录的 SKILL.md(frontmatter + body)和附属文件,与 parser 的解析格式一致。 */
function writeSnapshotSkill(
name: string,
metadata: SkillMetadata,
body: string,
files: RemoteSkillFile[] = [],
options: { replaceDir?: boolean } = {}
): void {View on GitHub (pinned to 81571269ad)
Solutions
- Ensure all file.path values in the remote skill are relative and stay under the skill root (no leading '/', no '..').
- Treat this as a security event: log and reject the entire skill rather than retrying, since path traversal is a likely attack.
- Normalize paths server-side before publishing the skill manifest.
- Add a unit test for resolveSnapshotFilePath covering '..' and absolute inputs.
Example fix
// before
const resolved = resolveSnapshotFilePath(skillDir, file.path)
if (!resolved) throw new Error(`invalid file path for "${name}": ${file.path}`)
// after: also strip leading slashes/.. defensively before resolving
const safe = file.path.replace(/^\/+/, '')
if (safe.includes('..')) throw new Error(`invalid file path for "${name}": ${file.path}`) Defensive patterns
Strategy: validation
Validate before calling
const safe = file.path.replace(/^\/+/, '')
if (safe.includes('..') || path.isAbsolute(file.path)) throw new Error(`invalid file path for "${name}": ${file.path}`) Type guard
function isInvalidFilePath(e: unknown): e is Error { return e instanceof Error && e.message.startsWith('invalid file path for') } Try / catch
try { await syncSkill(name, files) } catch (e) { if (isInvalidFilePath(e)) { reportUnsafeSkill(name, e.message); return } throw e } Prevention
- Treat path-traversal rejections as security events: log and block the skill.
- Normalize and validate paths server-side before publishing.
- Reject absolute paths and '..' segments at ingest time.
When it happens
Trigger: file.path contains '..' that escapes skillDir, an absolute path (/etc/x), a drive/rooted path on Windows, or after normalization (path.resolve) the resolved target does not begin with root+path.sep. The skill name is interpolated for context.
Common situations: Malicious or buggy remote skill manifest pointing at parent directories; paths with leading slash treated as absolute; symlink-like '..' chains; Windows drive letters producing a target that starts with a different root than skillDir.
Related errors
- invalid file entry for "${name}"
- duplicate file path for "${name}": ${resolved.normalizedPath
- Invalid skill name: path traversal not allowed
- Invalid script name: path traversal not allowed
- Script path escapes skills directory
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/4caf7cd1aaf8ef7c.
Report an issue: GitHub.