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 <amp@ampcode.com>
This commit is contained in:
Luke Mino-Altherr 2026-02-24 16:30:52 -08:00
parent 88ffc4d7c7
commit 9bdce59d62
2 changed files with 9 additions and 17 deletions

View File

@ -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

View File

@ -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(