invoke-ai/InvokeAI · error

Invalid image name, potential directory traversal detected

Error message

Invalid image name, potential directory traversal detected

What it means

ImageFileService.get_path validates that the image filename contains no path separators by comparing Path(filename).name to the original string. If they differ, the name embeds a directory component or traversal, so it raises this ValueError to prevent writing or reading outside the outputs folder.

Source

Thrown at invokeai/app/services/image_files/image_files_disk.py:259

        if not isinstance(token, _StagedDelete):
            raise ImageFileDeleteException("Invalid staged-delete token")
        try:
            for source, destination in reversed(token.files):
                if destination.exists():
                    source.parent.mkdir(parents=True, exist_ok=True)
                    destination.replace(source)
            shutil.rmtree(token.directory, ignore_errors=True)
        except Exception as e:
            raise ImageFileDeleteException from e

    def get_path(self, image_name: str, thumbnail: bool = False, image_subfolder: str = "") -> Path:
        base_folder = self.__thumbnails_folder if thumbnail else self.__output_folder
        filename = get_thumbnail_name(image_name) if thumbnail else image_name

        # Validate the filename itself (no path separators allowed in the filename)
        basename = Path(filename).name
        if basename != filename:
            raise ValueError("Invalid image name, potential directory traversal detected")

        # Build the full path with optional subfolder
        if image_subfolder:
            self._validate_subfolder(image_subfolder)
            image_path = base_folder / image_subfolder / basename
        else:
            image_path = base_folder / basename

        # Ensure the image path is within the base folder to prevent directory traversal
        resolved_base = base_folder.resolve()
        resolved_image_path = image_path.resolve()

        if not resolved_image_path.is_relative_to(resolved_base):
            raise ValueError("Image path outside outputs folder, potential directory traversal detected")

        return resolved_image_path

    @staticmethod

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Strip any directory components from the name before calling, or pass the directory via the image_subfolder parameter instead
  2. Sanitize the name with Path(name).name and verify it matches the input
  3. Reject the input at your API boundary with an allowlist regex (e.g. ^[A-Za-z0-9._-]+$)

Example fix

// before
service.save(Path('uploads/img.png').read_bytes(), 'subdir/img.png')
// after
service.save(Path('uploads/img.png').read_bytes(), 'img.png', image_subfolder='subdir')
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import PurePosixPath
import re
NAME_RE = re.compile(r'^[A-Za-z0-9][A-Za-z0-9._-]*$')
def is_safe_image_name(name: str) -> bool:
    return bool(NAME_RE.match(name)) and PurePosixPath(name).name == name
if not is_safe_image_name(image_name): raise ValueError('bad image name')

Type guard

def is_safe_image_name(name: object) -> bool:
    return isinstance(name, str) and '/' not in name and '\\' not in name and name not in ('', '.', '..')

Try / catch

try:
    path = service.get_path(image_name, thumbnail=False)
except ValueError as e:
    logger.warning('Rejected image name %r: %s', image_name, e)
    raise HTTPException(400, 'Invalid image name') from e

Prevention

When it happens

Trigger: Calling get/save/stage_delete with an image_name containing '/' or backslashes (e.g. '../foo.png' or 'sub/dir.png'), or a thumbnail name derived from such a name.

Common situations: Passing user-supplied or API-derived image names that include relative paths; storing images with names built by joining folder+file instead of using the image_subfolder parameter; older code predating the subfolder feature.

Related errors


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