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

  1. Change the 'file' value to a plain relative path inside the integration package (e.g. 'commands/plan.md').
  2. Move the referenced template into the integration's own directory tree instead of pointing elsewhere.
  3. 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

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


AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14). Data as JSON: /api/errors/1c6514b417c8702e. Report an issue: GitHub.