github/spec-kit · error · IntegrationDescriptorError

Script entry must be a relative path without '..': {script_e

Error message

Script entry must be a relative path without '..': {script_entry}

What it means

Raised by IntegrationDescriptor._validate() (src/specify_cli/integrations/catalog.py:813) when a provides.scripts entry is an absolute path, contains '..', or carries a drive/anchor component. Scripts are resolved inside the integration package, so only simple relative paths are accepted; the offending script_entry appears in the message.

Source

Thrown at src/specify_cli/integrations/catalog.py:813

            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"]

    @property
    def name(self) -> str:
        return self.data["integration"]["name"]

    @property
    def version(self) -> str:
        return self.data["integration"]["version"]

    @property

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Vendor the script into the integration package and reference it with a plain relative path.
  2. Strip leading slashes, drive letters, and '..' segments from the entry.
  3. Re-validate the descriptor.

Example fix

# before
provides:
  scripts:
    - /opt/shared/setup.sh

# after
provides:
  scripts:
    - scripts/bash/setup.sh
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def unsafe_scripts(scripts):
    return [s for s in scripts
            if Path(s).is_absolute() or ".." in Path(s).parts
            or Path(s).drive or Path(s).anchor]

Type guard

def is_safe_script_path(s: str) -> bool:
    p = Path(s)
    return not p.is_absolute() and ".." not in p.parts and not p.drive and not p.anchor

Prevention

When it happens

Trigger: 'provides: scripts: [/usr/local/bin/setup.sh]' or 'scripts: [../../lib/setup.sh]'; the combined isabs/'..'/drive/anchor check raises with the concrete path.

Common situations: Pointing at a system-wide script installed elsewhere on the machine; referencing a shared scripts directory outside the integration; Windows drive-letter paths copied into the descriptor.

Related errors


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