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)
The flush() method on lines 366-379 already catches OSError and ValueError
when calling original_stdout.flush() / original_stderr.flush(), but the
sync_write() method on line 361 and the tqdm branch in write() on line 336
do NOT. On Windows, when ComfyUI is launched as a child process with piped
stdio, certain conditions can leave the underlying handle in a state where
flush() raises OSError [Errno 22] Invalid argument.
Once that happens, the unhandled OSError propagates back through:
print() in any custom node
-> write(message) in this logger wrapper
-> sync_write(message)
-> original_*.flush()
-> OSError [Errno 22]
This kills prompt execution for any custom node that prints during
INPUT_TYPES() or __init__ -- even on a benign log line like
'Dependencies already installed from previous run' in LatentSyncWrapper.
Symptoms users will recognize:
- LatentSync, Sonic, Hallo 2 all failing with [Errno 22] before reading inputs
- 'Logging error' lines spammed throughout the console
- The error in the user's traceback always points back to
prestartup_script.py:361 / app/logger.py:35 super().flush()
Wrapping the flush calls in try/except (OSError, ValueError) -- the
exact same pattern already used in self.flush() on line 378 -- breaks
the cascade. Print failures degrade silently to file-only logging
instead of taking down prompt execution.
Adding the following node packs to the custom node list:
- ComfyUI-Darkroom: 29-node professional color grading & film emulation suite
- ComfyUI-Gemini-Direct: Direct Google Gemini image generation
- ComfyUI-API-Optimizer: API cost tracking and caching
- ComfyUI-Gemini-Conversation-Canvas: Multi-turn conversational image editing
- comfyui-wireless-link-simple: Wireless data transmission nodes
- ComfyUI-Higgsfield-Direct: Direct Higgsfield API integration
All repos are public, have proper __init__.py with NODE_CLASS_MAPPINGS,
and are published on the Comfy Registry under @akurate.