`path` and `filename` are free-form strings that can come from a
workflow's JSON, not just a person typing into the local UI. Only the
final path segment was ever sanitized (make_pathname/sanitize_filename),
so a value like `../../../etc` or an absolute path could make
ImageSaver.save_images() create directories and write the image/JSON
sidecar outside ComfyUI's output directory (CWE-22/CWE-73). This is
what caused v1.24.0 to be banned on the Comfy Registry
(Comfy-Org/registry-backend#206).
Add utils.resolve_within_output(), which joins path pieces onto
folder_paths.output_directory, resolves symlinks, and rejects the
result if it escapes that directory. Apply it everywhere
ImageSaver.save_images() turns `path`/`filename` into a filesystem
path: the output directory itself, the final image target, and the
optional workflow-JSON sidecar. Nested relative subfolders (e.g.
`portraits/2026-08-27`) still work; `..`, absolute paths, and
symlink escapes are now rejected before anything is created.
Covered by a new tests/ suite (tests/test_paths.py), since exercising
nodes.py requires stubbing ComfyUI's runtime (see tests/conftest.py).
Fixesalexopus/ComfyUI-Image-Saver#138
Update project documentation to reflect the newly introduced Pipe
architecture and improve overall clarity regarding workflow orchestration.
- `README.md`: Add a new "Optional: Pipe Integration" section explaining
when to use the pipe system, emphasizing its role in managing complex,
multi-stage workflows with deferred execution. Clarify the distinction
and compatibility boundaries between standard and pipe nodes.
- `README.md`: Document the `%counter<padding>` filename template variable.
- `CLAUDE.md`: Update the core architecture map to include `nodes_pipe.py`
and list the new configuration, modification, and terminal nodes.
- `examples/`: Introduce a dedicated examples directory. Move the standard
`example-workflow.json` into this folder and add the new
`image_saver_pipe_workflow.json` to demonstrate advanced orchestration.
- `examples/README.md`: Add a descriptive index detailing the differences
between the standard workflow and the advanced pipe orchestration example.
Introduce an optional Pipe architecture to streamline metadata management
and reduce wire clutter in complex, multi-stage workflows.
This new system utilizes deferred execution (lazy evaluation), passing
metadata and configuration state as raw dictionaries through the pipe.
Expensive operations, such as checkpoint hashing and Civitai API lookups,
are now deferred until the final image save execution. This approach
prevents premature data mutation and significantly reduces execution
overhead during workflow design and routing.
To maintain architectural cleanliness and follow existing module patterns,
these nodes are housed in a dedicated `nodes_pipe.py` file. The pipe
configuration uses dynamic dictionary composition to inherit UI definitions
safely without inheriting incorrect base execution logic.
Key additions:
- `MakeImageSaverSimpleConfig` & `MakeImageSaverMetadataConfig`: Provide
standalone input configurations.
- `MakeImageSaverPipe`: Bundles configurations into a single connection.
- `EditImageSaverPipe`: Enables non-destructive branching and overrides.
- `ReadImageSaverPipe`: Allows extraction of pipe data for external use.
- `ImageSaverFromPipe`: Triggers disk/network actions.
Add `apply_custom_counter_format` to support `%counter<padding>`
syntax in filenames (e.g., `%counter<03>` yields `001`). This
enhances customization across all image saver nodes.
Updates for Civitai Hash Fetcher improvements, file matching refactor,
and GGUF model support.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed `self.cached_hash` to `self.last_hash` on line 129 to match
the variable name used in __init__ (line 13) and the cache check (line 39).
Previously, the cache would save to the wrong variable name, causing
subsequent calls with the same parameters to return None instead of
the cached hash value.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Increase API result limit from 1 to 20 to work around Civitai's ranking issues
- Add nsfw parameter to include NSFW models in search results
- Add fallback to fetch all user models when search query returns no results
- Implement smart client-side matching for partial and exact name matches
Fixes issues where models weren't found due to:
1. Civitai API not returning model as top result with limit=1
2. NSFW models being filtered out by default
3. API search query parameter failing for certain model names