mirror of
https://github.com/Comfy-Org/ComfyUI-Manager.git
synced 2026-07-26 10:07:38 +08:00
feat(security): dedicated install flags decoupled from security_level (#2991)
Python Linting / Run Ruff (push) Waiting to run
Python Linting / Run Ruff (push) Waiting to run
* feat(security): add dedicated install flags decoupled from security_level Gate 'install via git URL' and 'install via pip' with dedicated opt-in boolean flags (allow_git_url_install / allow_pip_install) in config.ini [default], fully replacing the security_level term on those surfaces (REPLACE, not AND — a strict level no longer denies when the flag is on; a weak level no longer allows when the flag is off). - glob/manager_server.py: pure predicate is_dedicated_install_allowed (flag AND loopback, request-time args.listen); REPLACE gates at /customnode/install/git_url and /customnode/install/pip; batch unknown-URL arm routes through the same full predicate at the risky position (loopback term is load-bearing — the middle entry gate has no network-position term; the entry gate itself stays in force); unknown-pip in batch stays unconditionally blocked; new SECURITY_MESSAGE_FLAG_* denial constants name the responsible flag; security_403_response gains flag_token (comfyui_outdated keeps precedence) - glob/manager_core.py: register both keys (read via get_bool default-false, write list, exception fallback); "true"-only truthy; restart-only activation - js/common.js: 403 dialog copy names the responsible flag at the two install call sites - README.md: security-policy docs for both flags (per-surface scope incl. the batch entry-gate qualifier, REPLACE decoupling, loopback bound, opt-in config snippet, default-deny + migration note); stale tier lists corrected against the actual gates - CHANGELOG.md: opt-in migration note + accepted residual risk (flags bypass the forced-strong outdated-ComfyUI hardening on loopback, opt-in only), decoupling claim qualified for the batch entry gate Tests: unit suite (predicate truth table, REPLACE litmus both directions, AST binding-proofs against live handlers, subprocess-isolated config contract) plus a real-server E2E suite that mounts the Manager-under-test via git worktree (exact-SHA pin, detached) against a real ComfyUI and exercises both flag surfaces and both arms — deny arms (403 + flag-naming body/log + no install artifact), git-URL allow arm (real clone), pip allow arm as a two-phase reservation oracle — with zero-residual self-clean. Module skips without E2E_COMFYUI_ROOT; unit suite unaffected. The manager-v4 branch ships the identical policy (shared invariants + config contract); this tree uses the degraded predicate 'flag AND loopback' (no personal_cloud-equivalent mode here). * bump version to v3.41
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
"""Test-runner guard for the GOAL #32 tests/ modules.
|
||||
|
||||
WHY THIS FILE EXISTS (collection hazard, not test logic):
|
||||
|
||||
The repo root contains ``__init__.py`` — the ComfyUI plugin entrypoint —
|
||||
which at import time appends ``glob/`` to sys.path and imports
|
||||
``manager_server`` (which needs ``folder_paths`` / ``comfy.cli_args`` /
|
||||
a constructed ``PromptServer``). pytest 8 collects any ancestor
|
||||
directory that carries an ``__init__.py`` as a ``Package`` node and
|
||||
IMPORTS that ``__init__.py`` during test setup (observed module name:
|
||||
``__init__``). Outside a live ComfyUI process that import can never
|
||||
succeed, so EVERY test under tests/ errors at setup — including the
|
||||
pre-existing tests/test_csrf_content_type_helper.py — whenever pytest's
|
||||
rootdir ends up at or above the repo root (e.g. running inside a git
|
||||
worktree nested under the parent checkout).
|
||||
|
||||
The guard below pre-seeds ``sys.modules`` with an inert stub whose
|
||||
``__file__`` matches the real path, so pytest's
|
||||
``import_path(<repo-root>/__init__.py)`` resolves to the stub without
|
||||
executing the plugin entrypoint. Conftest files load before the setup
|
||||
phase, so the stub is always in place in time. This does NOT touch
|
||||
production code and does NOT alter what the tests import themselves
|
||||
(they use AST-extraction / subprocess isolation per the
|
||||
tests/test_csrf_content_type_helper.py precedent — ``glob/`` is never
|
||||
added to the runner's sys.path).
|
||||
"""
|
||||
import sys
|
||||
import types
|
||||
from pathlib import Path
|
||||
|
||||
_REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
_ROOT_INIT = _REPO_ROOT / "__init__.py"
|
||||
|
||||
if _ROOT_INIT.exists() and "__init__" not in sys.modules:
|
||||
_stub = types.ModuleType("__init__")
|
||||
_stub.__file__ = str(_ROOT_INIT)
|
||||
_stub.__doc__ = (
|
||||
"Inert stand-in for the ComfyUI-Manager plugin entrypoint; "
|
||||
"see tests/conftest.py for rationale."
|
||||
)
|
||||
sys.modules["__init__"] = _stub
|
||||
Reference in New Issue
Block a user