zylon-ai/private-gpt · warning · ValueError
'allOf' must be an array of schemas
Error message
'allOf' must be an array of schemas
What it means
Pydantic field-validator error on SkillFile.path when any '/'-separated segment equals '..' — the classic traversal pattern. It prevents skill file entries from escaping the skill root via relative traversal; FastAPI surfaces it as 422.
Source
Thrown at private_gpt/chat/schema_models.py:109
# Handle combinators first
if "oneOf" in schema:
if not isinstance(schema["oneOf"], list):
raise ValueError("'oneOf' must be an array of schemas")
for sub_schema in schema["oneOf"]:
_validate_json_schema_item(sub_schema, strict=False)
return # oneOf schemas don't need type field
if "anyOf" in schema:
if not isinstance(schema["anyOf"], list):
raise ValueError("'anyOf' must be an array of schemas")
for sub_schema in schema["anyOf"]:
_validate_json_schema_item(sub_schema, strict=False)
return # anyOf schemas don't need type field
if "allOf" in schema:
if not isinstance(schema["allOf"], list):
raise ValueError("'allOf' must be an array of schemas")
for sub_schema in schema["allOf"]:
_validate_json_schema_item(sub_schema, strict=False)
return # allOf schemas don't need type field
# Regular schema validation
if "type" not in schema:
if strict:
raise ValueError("Schema must define a 'type' field")
else:
return # Non-strict mode allows missing type
if schema["type"] == "array" and "items" not in schema:
raise ValueError("Array schemas must define 'items'")
if schema["type"] == "array" and not isinstance(schema.get("items"), dict):
raise ValueError("Array 'items' must be a dictionary representing JSON Schema")
# Recursively validate array itemsView on GitHub (pinned to 4a030776a3)
Solutions
- Sanitize: split on '/', drop '', '.' and '..' segments, rejoin with '/'.
- Reject input containing '..' before it reaches the API call.
- Use ids/names produced by your own listing flow instead of raw user strings.
Example fix
# before
path = f"{user_dir}/{user_input}" # user_input = '../../etc/passwd'
# after
parts = [s for s in f"{user_dir}/{user_input}".split('/') if s not in ('', '.', '..')]
if '..' in f"{user_dir}/{user_input}".split('/'):
raise ValueError('invalid path')
path = '/'.join(parts) Defensive patterns
Strategy: validation
Validate before calling
function sanitizeSkillPath(raw) {
if (raw.split('/').includes('..')) throw new Error('traversal rejected');
return raw.split('/').filter((s) => s && s !== '.').join('/');
} Type guard
const hasNoDotDot = (p) => typeof p === 'string' && !p.split('/').includes('..'); Prevention
- Reject '..' segments before they reach the API
- Never concatenate untrusted input into skill file paths
- Add security tests asserting traversal payloads fail client-side validation
When it happens
Trigger: Submitting path 'assets/../../SKILL.md' or any segment equal to '..'; naive concatenation of user input into the path field; security probing of the skills upload API.
Common situations: Client code joining a base directory with untrusted relative input; porting archives containing '..' entries; penetration tests expecting traversal to be blocked.
Related errors
- 'oneOf' must be an array of schemas
- 'anyOf' must be an array of schemas
- Invalid system specification (dict): {system}
- Provide SKILL.md either in files or skill_md
- UNSAFE_PATH_TRAVERSAL
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/0d1b65207986a6c0.
Report an issue: GitHub.