Fix #46 enable node blacklisting using --blacklist-custom-nodes ComfyUI-Manager / config.blacklist_custom_nodes = ["ComfyUI-Manager"]

This commit is contained in:
doctorpangloss 2025-09-23 13:50:05 -07:00
parent 2a881a768e
commit ac0694a7bd
9 changed files with 155 additions and 88 deletions

170
README.md
View File

@ -696,86 +696,67 @@ You can pass additional extra model path configurations with one or more copies
### Command Line Arguments ### Command Line Arguments
``` ```
usage: comfyui.exe [-h] [-c CONFIG_FILE] usage: comfyui [-h] [-c CONFIG_FILE]
[--write-out-config-file CONFIG_OUTPUT_PATH] [-w CWD] [--write-out-config-file CONFIG_OUTPUT_PATH] [-w CWD]
[--base-paths BASE_PATHS [BASE_PATHS ...]] [-H [IP]] [--base-paths BASE_PATHS [BASE_PATHS ...]] [-H [IP]]
[--port PORT] [--enable-cors-header [ORIGIN]] [--port PORT] [--enable-cors-header [ORIGIN]]
[--max-upload-size MAX_UPLOAD_SIZE] [--max-upload-size MAX_UPLOAD_SIZE]
[--base-directory BASE_DIRECTORY] [--base-directory BASE_DIRECTORY]
[--extra-model-paths-config PATH [PATH ...]] [--extra-model-paths-config PATH [PATH ...]]
[--output-directory OUTPUT_DIRECTORY] [--output-directory OUTPUT_DIRECTORY]
[--temp-directory TEMP_DIRECTORY] [--temp-directory TEMP_DIRECTORY]
[--input-directory INPUT_DIRECTORY] [--auto-launch] [--input-directory INPUT_DIRECTORY] [--auto-launch]
[--disable-auto-launch] [--cuda-device DEVICE_ID] [--disable-auto-launch] [--cuda-device DEVICE_ID]
[--cuda-malloc | --disable-cuda-malloc] [--default-device DEFAULT_DEVICE_ID]
[--force-fp32 | --force-fp16 | --force-bf16] [--cuda-malloc | --disable-cuda-malloc]
[--fp32-unet | --fp64-unet | --bf16-unet | --fp16-unet | --fp8_e4m3fn-unet | --fp8_e5m2-unet | --fp8_e8m0fnu-unet] [--force-fp32 | --force-fp16 | --force-bf16]
[--fp16-vae | --fp32-vae | --bf16-vae] [--cpu-vae] [--fp32-unet | --fp64-unet | --bf16-unet | --fp16-unet | --fp8_e4m3fn-unet | --fp8_e5m2-unet | --fp8_e8m0fnu-unet]
[--fp8_e4m3fn-text-enc | --fp8_e5m2-text-enc | --fp16-text-enc | --fp32-text-enc | --bf16-text-enc] [--fp16-vae | --fp32-vae | --bf16-vae] [--cpu-vae]
[--directml [DIRECTML_DEVICE]] [--fp8_e4m3fn-text-enc | --fp8_e5m2-text-enc | --fp16-text-enc | --fp32-text-enc | --bf16-text-enc]
[--oneapi-device-selector SELECTOR_STRING] [--directml [DIRECTML_DEVICE]]
[--disable-ipex-optimize] [--supports-fp8-compute] [--oneapi-device-selector SELECTOR_STRING]
[--preview-method [none,auto,latent2rgb,taesd]] [--disable-ipex-optimize] [--supports-fp8-compute]
[--preview-size PREVIEW_SIZE] [--preview-method [none,auto,latent2rgb,taesd]]
[--cache-classic | --cache-lru CACHE_LRU | --cache-none] [--preview-size PREVIEW_SIZE]
[--use-split-cross-attention | --use-quad-cross-attention | --use-pytorch-cross-attention | --use-sage-attention | --use-flash-attention] [--cache-classic | --cache-lru CACHE_LRU | --cache-none]
[--disable-xformers] [--use-split-cross-attention | --use-quad-cross-attention | --use-pytorch-cross-attention | --use-sage-attention | --use-flash-attention]
[--force-upcast-attention | --dont-upcast-attention] [--disable-xformers]
[--gpu-only | --highvram | --normalvram | --lowvram | --novram | --cpu] [--force-upcast-attention | --dont-upcast-attention]
[--reserve-vram RESERVE_VRAM] [--async-offload] [--gpu-only | --highvram | --normalvram | --lowvram | --novram | --cpu]
[--default-hashing-function {md5,sha1,sha256,sha512}] [--reserve-vram RESERVE_VRAM] [--async-offload]
[--disable-smart-memory] [--deterministic] [--force-non-blocking]
[--fast [FAST ...]] [--mmap-torch-files] [--disable-mmap] [--default-hashing-function {md5,sha1,sha256,sha512}]
[--dont-print-server] [--quick-test-for-ci] [--disable-smart-memory] [--deterministic] [--fast [FAST ...]]
[--windows-standalone-build] [--disable-metadata] [--mmap-torch-files] [--disable-mmap] [--dont-print-server]
[--disable-all-custom-nodes] [--quick-test-for-ci] [--windows-standalone-build]
[--whitelist-custom-nodes WHITELIST_CUSTOM_NODES [WHITELIST_CUSTOM_NODES ...]] [--disable-metadata] [--disable-all-custom-nodes]
[--disable-api-nodes] [--multi-user] [--create-directories] [--whitelist-custom-nodes WHITELIST_CUSTOM_NODES [WHITELIST_CUSTOM_NODES ...]]
[--log-stdout] [--blacklist-custom-nodes BLACKLIST_CUSTOM_NODES [BLACKLIST_CUSTOM_NODES ...]]
[--plausible-analytics-base-url PLAUSIBLE_ANALYTICS_BASE_URL] [--disable-api-nodes] [--multi-user] [--create-directories]
[--plausible-analytics-domain PLAUSIBLE_ANALYTICS_DOMAIN] [--log-stdout]
[--analytics-use-identity-provider] [--plausible-analytics-base-url PLAUSIBLE_ANALYTICS_BASE_URL]
[--distributed-queue-connection-uri DISTRIBUTED_QUEUE_CONNECTION_URI] [--plausible-analytics-domain PLAUSIBLE_ANALYTICS_DOMAIN]
[--distributed-queue-worker] [--distributed-queue-frontend] [--analytics-use-identity-provider]
[--distributed-queue-name DISTRIBUTED_QUEUE_NAME] [--distributed-queue-connection-uri DISTRIBUTED_QUEUE_CONNECTION_URI]
[--external-address EXTERNAL_ADDRESS] [--distributed-queue-worker] [--distributed-queue-frontend]
[--logging-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [--distributed-queue-name DISTRIBUTED_QUEUE_NAME]
[--disable-known-models] [--max-queue-size MAX_QUEUE_SIZE] [--external-address EXTERNAL_ADDRESS]
[--otel-service-name OTEL_SERVICE_NAME] [--logging-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
[--otel-service-version OTEL_SERVICE_VERSION] [--disable-known-models] [--max-queue-size MAX_QUEUE_SIZE]
[--otel-exporter-otlp-endpoint OTEL_EXPORTER_OTLP_ENDPOINT] [--otel-service-name OTEL_SERVICE_NAME]
[--force-channels-last] [--force-hf-local-dir-mode] [--otel-service-version OTEL_SERVICE_VERSION]
[--front-end-version FRONT_END_VERSION] [--otel-exporter-otlp-endpoint OTEL_EXPORTER_OTLP_ENDPOINT]
[--panic-when PANIC_WHEN] [--front-end-root FRONT_END_ROOT] [--force-channels-last] [--force-hf-local-dir-mode]
[--executor-factory EXECUTOR_FACTORY] [--front-end-version FRONT_END_VERSION]
[--openai-api-key OPENAI_API_KEY] [--panic-when PANIC_WHEN] [--front-end-root FRONT_END_ROOT]
[--ideogram-api-key IDEOGRAM_API_KEY] [--executor-factory EXECUTOR_FACTORY]
[--anthropic-api-key ANTHROPIC_API_KEY] [--openai-api-key OPENAI_API_KEY]
[--user-directory USER_DIRECTORY] [--ideogram-api-key IDEOGRAM_API_KEY]
[--enable-compress-response-body] [--anthropic-api-key ANTHROPIC_API_KEY]
[--comfy-api-base COMFY_API_BASE] [--user-directory USER_DIRECTORY]
[--database-url DATABASE_URL] [--enable-compress-response-body]
[--workflows WORKFLOWS [WORKFLOWS ...]] [--comfy-api-base COMFY_API_BASE] [--database-url DATABASE_URL]
[--blip-model-url BLIP_MODEL_URL] [--workflows WORKFLOWS [WORKFLOWS ...]]
[--blip-model-vqa-url BLIP_MODEL_VQA_URL]
[--sam-model-vith-url SAM_MODEL_VITH_URL]
[--sam-model-vitl-url SAM_MODEL_VITL_URL]
[--sam-model-vitb-url SAM_MODEL_VITB_URL]
[--history-display-limit HISTORY_DISPLAY_LIMIT]
[--ffmpeg-bin-path FFMPEG_BIN_PATH]
[--ffmpeg-extra-codecs FFMPEG_EXTRA_CODECS]
[--wildcards-path WILDCARDS_PATH]
[--wildcard-api WILDCARD_API]
[--photoprism-host PHOTOPRISM_HOST]
[--immich-host IMMICH_HOST]
[--ideogram-session-cookie IDEOGRAM_SESSION_COOKIE]
[--use-symlinks] [--ort-providers ORT_PROVIDERS]
[--vfi-ops-backend VFI_OPS_BACKEND]
[--dependency-version DEPENDENCY_VERSION] [--mmdet-skip]
[--sam-editor-cpu] [--sam-editor-model SAM_EDITOR_MODEL]
[--custom-wildcards CUSTOM_WILDCARDS]
[--disable-gpu-opencv]
options: options:
-h, --help show this help message and exit -h, --help show this help message and exit
-c CONFIG_FILE, --config CONFIG_FILE -c CONFIG_FILE, --config CONFIG_FILE
@ -829,7 +810,11 @@ options:
COMFYUI_DISABLE_AUTO_LAUNCH] COMFYUI_DISABLE_AUTO_LAUNCH]
--cuda-device DEVICE_ID --cuda-device DEVICE_ID
Set the id of the cuda device this instance will use. Set the id of the cuda device this instance will use.
[env var: COMFYUI_CUDA_DEVICE] All other devices will not be visible. [env var:
COMFYUI_CUDA_DEVICE]
--default-device DEFAULT_DEVICE_ID
Set the id of the default device, all other devices
will stay visible. [env var: COMFYUI_DEFAULT_DEVICE]
--cuda-malloc Enable cudaMallocAsync (enabled by default for torch --cuda-malloc Enable cudaMallocAsync (enabled by default for torch
2.0 and up). [env var: COMFYUI_CUDA_MALLOC] 2.0 and up). [env var: COMFYUI_CUDA_MALLOC]
--disable-cuda-malloc --disable-cuda-malloc
@ -941,13 +926,17 @@ options:
COMFYUI_RESERVE_VRAM] COMFYUI_RESERVE_VRAM]
--async-offload Use async weight offloading. [env var: --async-offload Use async weight offloading. [env var:
COMFYUI_ASYNC_OFFLOAD] COMFYUI_ASYNC_OFFLOAD]
--force-non-blocking Force ComfyUI to use non-blocking operations for all
applicable tensors. This may improve performance on
some non-Nvidia systems but can cause issues with some
workflows. [env var: COMFYUI_FORCE_NON_BLOCKING]
--default-hashing-function {md5,sha1,sha256,sha512} --default-hashing-function {md5,sha1,sha256,sha512}
Allows you to choose the hash function to use for Allows you to choose the hash function to use for
duplicate filename / contents comparison. Default is duplicate filename / contents comparison. Default is
sha256. [env var: COMFYUI_DEFAULT_HASHING_FUNCTION] sha256. [env var: COMFYUI_DEFAULT_HASHING_FUNCTION]
--disable-smart-memory --disable-smart-memory
Force ComfyUI to agressively offload to regular ram Force ComfyUI to aggressively offload to regular ram
instead of keeping models in vram when it can. [env instead of keeping models in VRAM when it can. [env
var: COMFYUI_DISABLE_SMART_MEMORY] var: COMFYUI_DISABLE_SMART_MEMORY]
--deterministic Make pytorch use slower deterministic algorithms when --deterministic Make pytorch use slower deterministic algorithms when
it can. Note that this might not make images it can. Note that this might not make images
@ -957,7 +946,8 @@ options:
deteriorating optimizations. Pass a list specific deteriorating optimizations. Pass a list specific
optimizations if you only want to enable specific optimizations if you only want to enable specific
ones. Current valid optimizations: fp16_accumulation ones. Current valid optimizations: fp16_accumulation
fp8_matrix_mult cublas_ops [env var: COMFYUI_FAST] fp8_matrix_mult cublas_ops autotune [env var:
COMFYUI_FAST]
--mmap-torch-files Use mmap when loading ckpt/pt files. [env var: --mmap-torch-files Use mmap when loading ckpt/pt files. [env var:
COMFYUI_MMAP_TORCH_FILES] COMFYUI_MMAP_TORCH_FILES]
--disable-mmap Don't use mmap when loading safetensors. [env var: --disable-mmap Don't use mmap when loading safetensors. [env var:
@ -980,6 +970,10 @@ options:
Specify custom node folders to load even when Specify custom node folders to load even when
--disable-all-custom-nodes is enabled. [env var: --disable-all-custom-nodes is enabled. [env var:
COMFYUI_WHITELIST_CUSTOM_NODES] COMFYUI_WHITELIST_CUSTOM_NODES]
--blacklist-custom-nodes BLACKLIST_CUSTOM_NODES [BLACKLIST_CUSTOM_NODES ...]
Specify custom node folders to never load. Accepts
shell-style globs. [env var:
COMFYUI_BLACKLIST_CUSTOM_NODES]
--disable-api-nodes Disable loading all api nodes. [env var: --disable-api-nodes Disable loading all api nodes. [env var:
COMFYUI_DISABLE_API_NODES] COMFYUI_DISABLE_API_NODES]
--multi-user Enables per-user storage. [env var: --multi-user Enables per-user storage. [env var:
@ -1119,10 +1113,10 @@ options:
standard in. [env var: COMFYUI_WORKFLOWS] standard in. [env var: COMFYUI_WORKFLOWS]
Args that start with '--' can also be set in a config file (config.yaml or Args that start with '--' can also be set in a config file (config.yaml or
config.json or specified via -c). Config file syntax allows: key=value, config.json or config.cfg or config.ini or specified via -c). Config file
flag=true, stuff=[a,b,c] (for details, see syntax at https://goo.gl/R74nmi). syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at
In general, command-line values override environment variables which override https://goo.gl/R74nmi). In general, command-line values override environment
config file values which override defaults. variables which override config file values which override defaults.
``` ```

View File

@ -148,6 +148,7 @@ def _create_parser() -> EnhancedConfigArgParser:
parser.add_argument("--disable-metadata", action="store_true", help="Disable saving prompt metadata in files.") parser.add_argument("--disable-metadata", action="store_true", help="Disable saving prompt metadata in files.")
parser.add_argument("--disable-all-custom-nodes", action="store_true", help="Disable loading all custom nodes.") parser.add_argument("--disable-all-custom-nodes", action="store_true", help="Disable loading all custom nodes.")
parser.add_argument("--whitelist-custom-nodes", type=str, nargs='+', default=[], help="Specify custom node folders to load even when --disable-all-custom-nodes is enabled.") parser.add_argument("--whitelist-custom-nodes", type=str, nargs='+', default=[], help="Specify custom node folders to load even when --disable-all-custom-nodes is enabled.")
parser.add_argument("--blacklist-custom-nodes", type=str, nargs='+', default=[], help="Specify custom node folders to never load. Accepts shell-style globs.")
parser.add_argument("--disable-api-nodes", action="store_true", help="Disable loading all api nodes.") parser.add_argument("--disable-api-nodes", action="store_true", help="Disable loading all api nodes.")
parser.add_argument("--multi-user", action="store_true", help="Enables per-user storage.") parser.add_argument("--multi-user", action="store_true", help="Enables per-user storage.")

View File

@ -166,6 +166,7 @@ class Configuration(dict):
front_end_root (Optional[str]): The local filesystem path to the directory where the frontend is located. Overrides --front-end-version. front_end_root (Optional[str]): The local filesystem path to the directory where the frontend is located. Overrides --front-end-version.
comfy_api_base (str): Set the base URL for the ComfyUI API. (default: https://api.comfy.org) comfy_api_base (str): Set the base URL for the ComfyUI API. (default: https://api.comfy.org)
database_url (str): Specify the database URL, e.g. for an in-memory database you can use 'sqlite:///:memory:'. database_url (str): Specify the database URL, e.g. for an in-memory database you can use 'sqlite:///:memory:'.
blacklist_custom_nodes (list[str]): Specify custom node folders to never load. Accepts shell-style globs.
whitelist_custom_nodes (list[str]): Specify custom node folders to load even when --disable-all-custom-nodes is enabled. whitelist_custom_nodes (list[str]): Specify custom node folders to load even when --disable-all-custom-nodes is enabled.
default_device (Optional[int]): Set the id of the default device, all other devices will stay visible. default_device (Optional[int]): Set the id of the default device, all other devices will stay visible.
""" """
@ -234,6 +235,7 @@ class Configuration(dict):
self.windows_standalone_build: bool = False self.windows_standalone_build: bool = False
self.disable_metadata: bool = False self.disable_metadata: bool = False
self.disable_all_custom_nodes: bool = False self.disable_all_custom_nodes: bool = False
self.blacklist_custom_nodes: list[str] = []
self.whitelist_custom_nodes: list[str] = [] self.whitelist_custom_nodes: list[str] = []
self.multi_user: bool = False self.multi_user: bool = False
self.plausible_analytics_base_url: Optional[str] = None self.plausible_analytics_base_url: Optional[str] = None

View File

@ -5,6 +5,7 @@ import importlib.util
import logging import logging
import os import os
import sys import sys
import fnmatch
import time import time
import types import types
from contextlib import contextmanager from contextlib import contextmanager
@ -222,6 +223,9 @@ def _vanilla_load_custom_nodes_2(node_paths: Iterable[str]) -> ExportedNodes:
if args.disable_all_custom_nodes and possible_module not in args.whitelist_custom_nodes: if args.disable_all_custom_nodes and possible_module not in args.whitelist_custom_nodes:
logger.info(f"Skipping {possible_module} due to disable_all_custom_nodes and whitelist_custom_nodes") logger.info(f"Skipping {possible_module} due to disable_all_custom_nodes and whitelist_custom_nodes")
continue continue
if any(fnmatch.fnmatch(possible_module, pattern) for pattern in args.blacklist_custom_nodes):
logger.info(f"Skipping {possible_module} due to blacklist_custom_nodes")
continue
time_before = time.perf_counter() time_before = time.perf_counter()
possible_exported_nodes = _vanilla_load_custom_nodes_1(module_path, ignore=base_node_names) possible_exported_nodes = _vanilla_load_custom_nodes_1(module_path, ignore=base_node_names)
# comfyui-manager mitigation # comfyui-manager mitigation

View File

@ -0,0 +1,18 @@
from comfy.nodes.package_typing import CustomNode, InputTypes, FunctionReturnsUIVariables
class ShouldNotExist(CustomNode):
@classmethod
def INPUT_TYPES(cls) -> InputTypes:
return {"required": {}}
FUNCTION = "execute"
OUTPUT_NODE = True
def execute(self) -> tuple[...,]:
return None,
NODE_CLASS_MAPPINGS = {
"ShouldNotExist": ShouldNotExist
}

View File

@ -0,0 +1,48 @@
import pytest
from importlib.resources import files
from comfy.api.components.schema.prompt import Prompt
from comfy.cli_args_types import Configuration
from comfy.client.embedded_comfy_client import Comfy
_TEST_WORKFLOW_1 = {
"0": {
"inputs": {},
"class_type": "ShouldNotExist",
"_meta": {
"title": ""
}
},
"1": {
"inputs": {},
"class_type": "TestPath",
"_meta": {
"title": ""
}
}
}
_TEST_WORKFLOW_2 = {
"1": {
"inputs": {},
"class_type": "TestPath",
"_meta": {
"title": ""
}
}
}
@pytest.mark.asyncio
async def test_blacklist_node():
config = Configuration(blacklist_custom_nodes=['issue_46'])
# for finding the custom nodes
config.base_paths = [str(files(__package__))]
async with Comfy(config) as client:
from comfy.cmd.execution import validate_prompt
res = await validate_prompt("1", prompt=_TEST_WORKFLOW_1, partial_execution_list=[])
assert "ShouldNotExist" in res.error["message"]
assert res.error["type"] == "invalid_prompt"
res = await validate_prompt("2", prompt=_TEST_WORKFLOW_2, partial_execution_list=[])
assert "TestPath" not in res.error, "successfully loaded issue_25 nodes"