ComfyUI_frontend is moving to one LGraph instance per workflow tab
(Comfy-Org/ComfyUI_frontend#21571), and app.clean() clears the new graph
before any extension hook fires. The instance patch on app.graph.clear
only reaches the graph that existed at startup, so components would not
be reloaded for later workflows.
Patch clear on the graph prototype and reload components when the
cleared graph is the current root graph. This also stops a subgraph
clear from clearing the root graph, which the old wrapper did by always
calling orig_clear on app.graph.
Amp-Thread-ID: https://ampcode.com/threads/T-d545a10a-f002-4dc5-9a74-f6402a836919
The dialog renders HTML, so run the server body and the pack title
(registry-derived) through the existing sanitizeHTML() at both sites. The
title is wrapped in String() so a missing title can't throw inside the error
handler; rendered text is unchanged for ordinary values.
The batch install/uninstall paths replaced the server's 404 body with a
false "default channel" lead. Drop the 404 branch so a 404 falls through to
the existing server-text path; uninstall never returns 404 anyway. Fixes
#3128 (section 1), reported by plz12345.
The install-denial diagnostics named the wrong gate, sending users to
settings that could not resolve their denial:
- SECURITY_MESSAGE_FLAG_GIT_URL / _FLAG_PIP omitted the loopback half of
the flag-AND-loopback predicate, telling users to enable a flag that
was often already enabled. They now state both conditions, print the
live --listen value at every emission site, and explain that both
values are read once at startup (stop the server, edit, then start).
- SECURITY_MESSAGE_MIDDLE_OR_BELOW instructed setting security_level to
'middle', a value that does not exist; it now names only real values
(any level other than 'strong': normal, normal-, weak).
- The blocked-risk arm reused SECURITY_MESSAGE_GENERAL, blaming
security_level although no value of it can help there; it now emits a
dedicated SECURITY_MESSAGE_BLOCKED_RISK stating this is not a
configuration problem.
- SECURITY_MESSAGE_NORMAL_MINUS_MODEL now names its loopback-listener
condition and the same restart guidance.
- The js/common.js dedicated-403 messages mirror the loopback clause.
* 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
Defense-in-depth over GET→POST alone: reject the three CORS-safelisted
simple-form Content-Types (x-www-form-urlencoded, multipart/form-data,
text/plain) on 5 no-body POST handlers (snapshot/save,
manager/queue/{reset,start,update_comfyui}, manager/reboot) to block
<form method=POST> CSRF that bypasses method-only gating. Convert 10 pure
state-changing endpoints (fetch_updates, queue/{update_all,reset,start,
update_comfyui}, snapshot/{remove,restore,save}, comfyui_switch_version,
reboot) from GET to POST and split 5 config endpoints
(db_mode/preview_method/channel_url_list/policy/{component,update}) into
GET(read) + POST(write, JSON body). Emit the in_progress + done event pair
from the /manager/queue/install sync-enable fast-path so client UI
finalizes (previously only queue/start's empty worker done fired, leaving
item.restart unset and the Enable button visible after a successful enable).
Harden js/custom-nodes-manager.js completion path: await onQueueCompleted
with try/catch (surfaces silent turbogrid stale-item throws), replace the
{}.length == 0 no-op empty guard, set install_context before queue/install
to avoid a sync-completion race, wrap classList/updateCell in try/catch.
Resynchronize openapi.yaml with the converted routes (method → post, query
params → requestBody JSON schema, sibling post on 5 split endpoints).
Update 31 JS fetchApi call sites across 7 files; add
tests/test_csrf_content_type_helper.py covering 5 Content-Type cases via
aiohttp TestClient.
Reported-by: XlabAI Team of Tencent Xuanwu Lab
CVSS: 8.1 (AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H)
handleFile signature is updated in ComfyUI frontend [handleFile (file: File, openSource?: WorkflowOpenSource, options?: { deferWarnings?: boolean } )]. Using rest parameters to fix and future-proof.
- Add detection for ComfyUI PR #11261 (per-queue preview override)
- Return DISABLED status when native feature is detected
- Improve UI loading state and prevent flash of enabled state
- Add accessibility attributes and visual feedback for disabled state
- Show user notification when feature transitions to native
- Version bump to 3.39
* Started changing UI to match the rest of ComfyUI
Completed Main Container
* - Added layout formatting to components of the Manager dialog box
- Pulled name from select and put it into a label (eg "DB: Channel" now has a label of DB and a dropdown with channel, etc)
- Fixed incorrect z-index
* Removed this.close() I added before finding z-index issue.
* Matched buttons and drop downs to match style of ComfyUI interface while keeping the colours the same as OG ComfyUI Manager
* - Took gui building out and put into its own .js
- Applied theme to Nodes Manager
- Made theme respect user theme colors
* - Themed model manager and snapshot manager
- fixed incorrect id in gui builder
* Fix syntax error in color property
---------
Co-authored-by: Dr.Lt.Data <128333288+ltdrdata@users.noreply.github.com>
- Migrate Manager data path: default/ComfyUI-Manager → __manager
- Force security_level=strong on outdated ComfyUI (block installations)
- Auto-migrate config.ini only; backup legacy files for manual verification
- Raise weak/normal- to normal during migration
- Add /manager/startup_alerts API for UI warnings
- Differentiate 403 responses: comfyui_outdated vs security_level
- Block startup scripts execution on old ComfyUI
Requires ComfyUI v0.3.76+ for full functionality.
Backward compatible with older versions (uses legacy path).
* retain initial node_versions on serialize
* give precedence to workflow version
* set version info on node
* move patch to setup hook
* switch to nodeCreated
fixed: Update all - Properly display the results of the ComfyUI update.
fixed: Update all - An issue where the action results of the custom nodes manager were reflected in the main dialog.
https://github.com/ltdrdata/ComfyUI-Manager/issues/1548