invoke-ai/InvokeAI · error

Sidecar path outside outputs folder, potential directory tra

Error message

Sidecar path outside outputs folder, potential directory traversal detected

What it means

After joining the sidecars folder, subfolder, and sidecar filename, __get_sidecar_path resolves the result and verifies it is still relative to the sidecars base. If not, it means traversal escaped the outputs root (e.g. an absolute video_name or '..' that survived earlier checks, or symlink resolution). This is a defense-in-depth filesystem containment check.

Source

Thrown at invokeai/app/services/video_files/video_files_disk.py:230

        if subfolder.startswith("/"):
            raise ValueError("Absolute paths not allowed in subfolder path")
        for part in subfolder.split("/"):
            if part == "..":
                raise ValueError("Parent directory references not allowed in subfolder path")
            if part == "":
                raise ValueError("Empty path segments not allowed in subfolder path")

    def __get_sidecar_path(self, video_name: str, video_subfolder: str = "") -> Path:
        sidecar_name = Path(video_name).stem + ".json"
        if video_subfolder:
            self._validate_subfolder(video_subfolder)
            sidecar_path = self.__sidecars_folder / video_subfolder / sidecar_name
        else:
            sidecar_path = self.__sidecars_folder / sidecar_name
        resolved_base = self.__sidecars_folder.resolve()
        resolved_sidecar_path = sidecar_path.resolve()
        if not resolved_sidecar_path.is_relative_to(resolved_base):
            raise ValueError("Sidecar path outside outputs folder, potential directory traversal detected")
        return resolved_sidecar_path

    def __read_sidecar(self, video_name: str, video_subfolder: str = "") -> Optional[dict]:
        path = self.__get_sidecar_path(video_name, video_subfolder=video_subfolder)
        if not path.exists():
            return None
        try:
            with open(path, encoding="utf-8") as f:
                return json.load(f)
        except Exception as e:
            raise VideoFileNotFoundException from e

    def __validate_storage_folders(self) -> None:
        for folder in (self.__output_folder, self.__thumbnails_folder, self.__sidecars_folder):
            folder.mkdir(parents=True, exist_ok=True)

    def __recover_staged_deletes(self) -> None:
        logger = InvokeAILogger.get_logger()

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Ensure video_name contains no path separators or '..' before calling any sidecar operation
  2. Check for symlinks inside the outputs/sidecars directories that resolve outside the root and remove them
  3. Catch ValueError and surface a 4xx-style validation error to the caller instead of a 500

Example fix

// before
svc.save(video_name="../../etc/evil", payload)
// after
if "/" in video_name or "\\" in video_name or ".." in video_name:
    raise ValueError("invalid video name")
svc.save(video_name=video_name, payload)
Defensive patterns

Strategy: validation

Validate before calling

import re
NAME_RE = re.compile(r"^[A-Za-z0-9._-]+$")
def safe_video_name(name: str) -> bool:
    return bool(NAME_RE.match(name)) and ".." not in name

Type guard

def is_valid_video_name(name: str) -> bool:
    return isinstance(name, str) and "/" not in name and "\\" not in name and ".." not in name

Try / catch

try:
    sidecar = service.read_sidecar_metadata(video_name, subfolder=sub)
except ValueError as e:
    if "directory traversal" in str(e):
        log.warning("blocked traversal attempt: %s", video_name)
        sidecar = None
    else:
        raise

Prevention

When it happens

Trigger: __get_sidecar_path called from save, stage_delete, __read_sidecar or __recover_staged_deletes where the composed path resolves outside the sidecars folder — e.g. video_name containing '..' (only the subfolder is validated, not the name), or a symlink pointing outward.

Common situations: Malicious or buggy callers passing crafted video_name values; symlinked subdirectories inside outputs; upgraded code paths that bypass _validate_subfolder.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/ea7a273e7cf8a21b. Report an issue: GitHub.