github/spec-kit · error · IntegrationDescriptorError
Command entry 'file' must be a relative path without '..': {
Error message
Command entry 'file' must be a relative path without '..': {cmd_file} What it means
Raised by IntegrationDescriptor._validate() (src/specify_cli/integrations/catalog.py:804) when a provides.commands 'file' path is absolute, contains '..' segments, or has a drive/anchor component. The library only accepts simple relative paths so command files cannot point outside the integration package (path-traversal defense). The offending path is included in the message.
Source
Thrown at src/specify_cli/integrations/catalog.py:804
raise IntegrationDescriptorError(
"Each command entry must be a mapping"
)
if "name" not in cmd or "file" not in cmd:
raise IntegrationDescriptorError(
"Command entry missing 'name' or 'file'"
)
cmd_name = cmd["name"]
cmd_file = cmd["file"]
if not isinstance(cmd_name, str) or not cmd_name.strip():
raise IntegrationDescriptorError(
"Command entry 'name' must be a non-empty string"
)
if not isinstance(cmd_file, str) or not cmd_file.strip():
raise IntegrationDescriptorError(
"Command entry 'file' must be a non-empty string"
)
if os.path.isabs(cmd_file) or ".." in Path(cmd_file).parts or Path(cmd_file).drive or Path(cmd_file).anchor:
raise IntegrationDescriptorError(
f"Command entry 'file' must be a relative path without '..': {cmd_file}"
)
for script_entry in scripts:
if not isinstance(script_entry, str) or not script_entry.strip():
raise IntegrationDescriptorError(
"Script entry must be a non-empty string"
)
if os.path.isabs(script_entry) or ".." in Path(script_entry).parts or Path(script_entry).drive or Path(script_entry).anchor:
raise IntegrationDescriptorError(
f"Script entry must be a relative path without '..': {script_entry}"
)
# -- Property accessors -----------------------------------------------
@property
def id(self) -> str:
return self.data["integration"]["id"]
View on GitHub (pinned to bf88c9f9a8)
Solutions
- Change the 'file' value to a plain relative path inside the integration package (e.g. 'commands/plan.md').
- Move the referenced template into the integration's own directory tree instead of pointing elsewhere.
- Remove any '..' segments, leading '/', and drive letters; re-validate.
Example fix
# before - name: plan file: ../shared/plan.md # after - name: plan file: commands/plan.md
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def is_safe_relative(p: str) -> bool:
path = Path(p)
return (
not path.is_absolute()
and ".." not in path.parts
and not path.drive
and not path.anchor
) Type guard
def is_safe_command_file(entry: dict) -> bool:
f = entry.get("file")
return isinstance(f, str) and is_safe_relative(f) Prevention
- Keep all command templates inside the integration package directory.
- Use plain relative paths without '..' segments.
- Never reference files by absolute or Windows drive paths in descriptors.
When it happens
Trigger: A command entry with 'file: /etc/passwd', 'file: ../shared/plan.md', or 'file: C:\\cmds\\plan.md'; the combined isabs/parts/drive/anchor check trips and raises with the concrete cmd_file value.
Common situations: Using an absolute path to a shared template during local development; referencing a file in a sibling package with '../'; porting a descriptor from Windows with a drive letter; symlink-free escape attempts.
Related errors
- Script entry must be a relative path without '..': {script_e
- Output path {candidate!r} escapes directory {base!r}
- Invalid command name {cmd_name!r}: {name_reason}
- Invalid command alias {alias!r}: {alias_reason}
- Invalid Copilot prompt name {cmd_name!r}: {name_reason}
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/1c6514b417c8702e.
Report an issue: GitHub.