Files
jesse890423 c159dc4eaf security: resolve custom_model_path inside ComfyUI's model folders
This addresses the remaining point on #3335.

`VoiceCloneNode` and `CustomVoiceNode` passed the free-text
`custom_model_path` widget straight to `load_qwen_model()`, which checked
it with `os.path.exists()` / `os.path.isdir()` before anything else. That
is two problems in one: a shared workflow can name a folder anywhere on
the host and have a model loaded from it, and on Windows a path that
names another machine makes this host connect to it during that very
check, which is enough to hand that machine the user's sign-in
credentials.

- `_resolve_custom_model_dir()` treats the widget as a folder name
  relative to a fixed set of bases that the local installation decides,
  never the workflow: `models/qwen-tts` (plus whatever
  extra_model_paths.yaml registers under `qwen-tts` / `TTS`), and
  `output/qwen3tts_finetune`, where the Train node writes its
  checkpoints, so "fine-tune then generate" keeps working.
- Network share paths and absolute paths are refused before any
  filesystem call; the remaining relative value goes through the
  existing `_resolve_within()` (realpath + commonpath) with an existence
  check.
- The resolution happens before the tokenizer check and the model cache
  key, so nothing touches the path first and differently spelled values
  cannot split or poison the cache.
- An unusable value now raises instead of printing a warning and
  silently falling back, so a shared workflow cannot quietly change
  which model gets loaded.
- The Train node returns the checkpoint as a relative folder name (the
  absolute location is printed in the console) to match what
  `custom_model_path` accepts.
- Model search folders were factored into `_model_search_roots()`, which
  the loader now uses as well.
- Widget placeholders and tooltips, both READMEs, doc/update.md and the
  fine-tuning example workflow were updated accordingly.
2026-10-08 23:29:46 +08:00
..