Skip to content

Commit 6288fb0

Browse files
committed
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).
1 parent 3772432 commit 6288fb0

25 files changed

Lines changed: 9998 additions & 8815 deletions

CHANGELOG.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Changelog
2+
3+
## Unreleased
4+
5+
### Security policy: dedicated install flags (`allow_git_url_install` / `allow_pip_install`)
6+
7+
Two new boolean keys in `config.ini` (`[default]` section), both defaulting to
8+
`false`, now govern the arbitrary-install surfaces:
9+
10+
| Flag | Governs |
11+
|------|---------|
12+
| `allow_git_url_install` | `POST /customnode/install/git_url` and the unknown-git-URL arm of `POST /manager/queue/install` (incl. reinstall delegation) — the entire install transaction, transitive dependency pip installs included. On the batch queue path the flag applies **in addition to** the queue's `security_level` entry gate (see below) |
13+
| `allow_pip_install` | `POST /customnode/install/pip` only |
14+
15+
These surfaces additionally require a **loopback listener** (`--listen` on a
16+
local IP); the flags never open a non-loopback deployment. On the two
17+
**direct** endpoints (`POST /customnode/install/git_url` and
18+
`POST /customnode/install/pip`), the flags fully **decouple** the surface
19+
from `security_level`: it no longer has any effect in either direction — a
20+
strict level cannot deny them when the flag is `true`, and a weak level
21+
cannot allow them when the flag is `false`. On the **batch queue path**
22+
(`POST /manager/queue/install`), the flag is **necessary but not
23+
sufficient**: it gates the unknown-git-URL arm at the risky position, while
24+
the queue's normal `security_level` entry gate (`middle`) remains in force —
25+
at `security_level = strong`, batch unknown-URL installs stay denied even
26+
with the flag set to `true`. `security_level` continues to govern every
27+
other gated endpoint unchanged. Only the case-insensitive string `true`
28+
enables a flag; a missing or malformed key reads as `false`.
29+
30+
#### Migration note (no auto-seed)
31+
32+
There is **no automatic migration** from `security_level`. Users who
33+
previously relied on `security_level = weak` (or `normal-`) to use
34+
install-via-git-URL / install-pip must now **opt in explicitly** by adding to
35+
`config.ini`:
36+
37+
```ini
38+
[default]
39+
allow_git_url_install = true
40+
allow_pip_install = true
41+
```
42+
43+
Changes take effect after a **restart** (no hot reload).
44+
45+
#### Residual-risk note — outdated ComfyUI behavior change
46+
47+
On outdated ComfyUI versions (no system-user API), the manager previously
48+
forced `security_level = strong`, which unconditionally denied the
49+
git-URL/pip install surfaces. After this change those surfaces are governed
50+
by the new flags instead: an operator who explicitly sets a flag to `true`
51+
on a **loopback** listener can now perform installs on outdated ComfyUI
52+
where the forced-strong policy previously denied them. This is an accepted,
53+
deliberate trade-off: it requires explicit operator opt-in, remains bounded
54+
to loopback listeners, and the flag-deny path on outdated ComfyUI still
55+
surfaces the `comfyui_outdated` notice. If you operate an outdated ComfyUI
56+
deployment, leave both flags at their default `false` and update ComfyUI.

README.md

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,19 +384,79 @@ When you run the `scan.sh` script:
384384
* all feature is available
385385
386386
* `high` level risky features
387-
* `Install via git url`, `pip install`
388-
* Installation of custom nodes registered not in the `default channel`.
389-
* Fix custom nodes
387+
* Downloading models that are not in `.safetensors` format and not
388+
registered in the `default channel` model list
389+
* NOTE: `Install via git url`, `pip install`, and installation of custom nodes
390+
not registered in the `default channel` are **no longer governed by
391+
`security_level`** — they are governed by the dedicated install flags
392+
described below.
390393
391394
* `middle` level risky features
392395
* Uninstall/Update
393396
* Installation of custom nodes registered in the `default channel`.
397+
* Fix custom nodes
394398
* Restore/Remove Snapshot
395399
* Restart
396400
397401
* `low` level risky features
398402
* Update ComfyUI
399403
404+
### Dedicated install flags: `allow_git_url_install` / `allow_pip_install`
405+
406+
The two arbitrary-install surfaces are governed by dedicated boolean keys in
407+
`config.ini` (`[default]` section), fully **decoupled** from `security_level`:
408+
409+
* `allow_git_url_install`
410+
* governs `Install via Git URL` (`POST /customnode/install/git_url`) **and**
411+
the unknown-git-URL arm of the batch install queue
412+
(`POST /manager/queue/install`, including reinstall delegation) — i.e.
413+
installing any custom node from a git URL that is not registered in the
414+
`default channel` catalog
415+
* on the **batch queue path**, the flag is **necessary but not
416+
sufficient**: the queue's normal `security_level` entry gate (`middle`)
417+
must ALSO pass — at `security_level = strong`, batch unknown-URL
418+
installs stay denied even with the flag set to `true` (only the direct
419+
`Install via Git URL` endpoint is fully independent of `security_level`)
420+
* covers the **entire install transaction** it starts, including the
421+
pack's transitive dependency pip installs
422+
* `allow_pip_install`
423+
* governs **only** the standalone `pip install` feature
424+
(`POST /customnode/install/pip`)
425+
426+
Key properties:
427+
428+
* **Decoupled from `security_level` (replace, not and)** — on the two
429+
**direct endpoints** (`Install via Git URL` and `pip install`),
430+
`security_level` no longer has any effect in either direction: a strict
431+
level cannot deny them when the flag is `true`, and a weak level cannot
432+
allow them when the flag is `false`. (The batch queue path keeps its
433+
`security_level` entry gate in ADDITION to the flag — see the scope bullet
434+
above.) Every other gated feature remains governed by `security_level` as
435+
described above.
436+
* **Loopback only** — the flags take effect **only** when the server listens
437+
on a loopback address (e.g. `--listen 127.0.0.1`). On a non-loopback
438+
listener these surfaces stay denied regardless of the flags; the flags
439+
never widen the exposure of a public deployment.
440+
* **Default deny / explicit opt-in** — both flags default to `false`. Only
441+
the case-insensitive string `true` enables a flag; a missing or malformed
442+
key reads as `false`.
443+
444+
To opt in, edit `config.ini`:
445+
446+
```ini
447+
[default]
448+
allow_git_url_install = true
449+
allow_pip_install = true
450+
```
451+
452+
Changes take effect after a **restart** (no hot reload).
453+
454+
> **Migration note**: there is no automatic migration from `security_level`.
455+
> If you previously relied on `security_level = weak` (or `normal-`) to use
456+
> install-via-git-URL / pip install, you must opt in explicitly with the flags
457+
> above. See `CHANGELOG.md` for details, including a behavior note for
458+
> outdated ComfyUI deployments.
459+
400460

401461
# Disclaimer
402462

0 commit comments

Comments
 (0)