From 9bdce59d62d782ede54cec4f1689ae28f463f20b Mon Sep 17 00:00:00 2001 From: Luke Mino-Altherr Date: Tue, 24 Feb 2026 16:30:52 -0800 Subject: [PATCH] fix: replace os.path.commonpath with Path.is_relative_to for cross-drive safety commonpath raises ValueError on Windows when comparing paths on different drives (e.g. C:\models vs D:\extra_models). Replace all usages in the asset scanner with Path.is_relative_to() which handles cross-drive paths, case-insensitivity, and prefix traps natively without try/except. Amp-Thread-ID: https://ampcode.com/threads/T-019c9224-d83c-7797-8c02-e1e1ae2ee452 Co-authored-by: Amp --- app/assets/scanner.py | 11 +++++------ app/assets/services/path_utils.py | 15 ++++----------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/app/assets/scanner.py b/app/assets/scanner.py index ffb92f6a3..85c77dfa4 100644 --- a/app/assets/scanner.py +++ b/app/assets/scanner.py @@ -1,7 +1,7 @@ -import contextlib import logging import os import time +from pathlib import Path from typing import Literal, TypedDict import folder_paths @@ -89,12 +89,11 @@ def collect_models_files() -> list[str]: continue abs_path = os.path.abspath(abs_path) allowed = False + abs_p = Path(abs_path) for b in bases: - base_abs = os.path.abspath(b) - with contextlib.suppress(ValueError): - if os.path.commonpath([abs_path, base_abs]) == base_abs: - allowed = True - break + if abs_p.is_relative_to(os.path.abspath(b)): + allowed = True + break if allowed: out.append(abs_path) return out diff --git a/app/assets/services/path_utils.py b/app/assets/services/path_utils.py index c2be4bb52..22be7b18b 100644 --- a/app/assets/services/path_utils.py +++ b/app/assets/services/path_utils.py @@ -53,13 +53,9 @@ def resolve_destination_from_tags(tags: list[str]) -> tuple[str, list[str]]: def validate_path_within_base(candidate: str, base: str) -> None: - cand_abs = os.path.abspath(candidate) - base_abs = os.path.abspath(base) - try: - common = os.path.commonpath([cand_abs, base_abs]) - except Exception: - raise ValueError("invalid destination path") - if common != base_abs: + cand_abs = Path(os.path.abspath(candidate)) + base_abs = Path(os.path.abspath(base)) + if not cand_abs.is_relative_to(base_abs): raise ValueError("destination escapes base directory") @@ -108,10 +104,7 @@ def get_asset_category_and_relative_path( fp_abs = os.path.abspath(file_path) def _check_is_within(child: str, parent: str) -> bool: - try: - return os.path.commonpath([child, parent]) == parent - except Exception: - return False + return Path(child).is_relative_to(parent) def _compute_relative(child: str, parent: str) -> str: return os.path.relpath(