cd /news/ai-tools/one-bug-made-the-cut-lucent-on-comfy… · home topics ai-tools article
[ARTICLE · art-91255] src=blog.attacks.ai ↗ pub= topic=ai-tools verified=true sentiment=· neutral

One Bug Made the Cut: Lucent on ComfyUI

An audit of ComfyUI by a former Stability AI CISO found one vulnerability that made the cut: an arbitrary file write outside the output directory via dataset "Save" nodes, filed as a Medium-severity GitHub advisory. The audit, which cost about 1.8 cents in cloud compute, concluded ComfyUI is well-built under its single-trusted-operator threat model but noted that multi-user mode is not authentication and the Manager's security levels allow more at default than the name suggests.

read8 min views1 publishedAug 11, 2026
One Bug Made the Cut: Lucent on ComfyUI
Image: Blog (auto-discovered)

I aimed the hunter from the last post at something bigger and more popular than hermes-agent: ComfyUI, together with its companion

. If you have not run it, ComfyUI is a node-graph editor for image and video generation: you wire nodes into a workflow (load a checkpoint, encode a prompt, sample, decode, save) and a local server executes the graph. It became the power-user's interface for Stable Diffusion and the open image and video models that followed, the tool people reach for when a single-box web UI runs out of room. The project carries tens of thousands of GitHub stars and a custom-node ecosystem in the thousands, and the team behind it has since spun out as Comfy Org. I have history with this one: I was CISO at

ComfyUI-ManagerStability AI, where ComfyUI sat in the stack I was responsible for, so pointing the hunter at it was personal as much as a stress test.

And the surface is wide. ComfyUI serves an unauthenticated HTTP API that executes user-submitted workflow graphs, it loads third-party "custom nodes" as Python, and the Manager can install packages, switch versions, and reboot the server. A lot for a bug-hunter to pull on.

The honest headline first: ComfyUI is well-built. At its defaults it holds, and the audit did not turn up a dropped remote-code-execution hole. The more useful result is about its threat model. ComfyUI assumes a single trusted operator on localhost, and under that assumption its defenses are consistent. The risk is in the things a user might assume are security boundaries and that are not. Multi-user mode is not authentication. The Manager's "security levels" allow more at the default than the name suggests. And nothing in the product stops you putting the whole thing on a network it was never designed to face.

A word on the tool, because it cuts against the last post. The cheap part is the local automated sweep, this time a 14B Qwen reading 645 files one at a time. It found nothing real. ComfyUI is hardened enough that a shallow per-file pass slides off it; its real weak points are cross-file and architectural, which a per-file reader does not see. Everything below came out of the slower layer that reads the actual source against the evidence ladder and tries to disprove each lead. That is the part I said last time was where the value is. The cloud bill for the run was about 1.8 cents.

What made the cut #

Lucent surfaced the usual stack of leads. The discipline from last time still applies: read each one against the source, try to break it. But a target with a published SECURITY.md

adds a second ruler. Does the thing even count as a vulnerability under the project's own threat model? Measured that way, one finding made the cut.

What Where Verdict
Arbitrary file write outside output/
dataset "Save" nodes, from a loaded workflow In scope: filed as a GitHub advisory (Medium)
Path traversal → read an image from outside the models tree /experiment/models/preview
Real; image-bounded here, browser vector blocked by default. A later round found a verbatim read in this class (
torch.load with no weights_only on attacker bytes
LoadTrainingDataset , via /prompt
Real, but latent on a default torch (≥2.6 blocks it); RCE only on stale torch<2.6
Admin actions (reboot, snapshot/restore) reachable unauthenticated at the default ComfyUI-Manager Hardening: admin / denial-of-service, not RCE
install_model fetches an unchecked URL for .safetensors names
ComfyUI-Manager Hardening: SSRF + model poisoning
Bearer tokens written in cleartext to a web-served log directory API-node request logger Low
Websocket client-id can be taken over → another client's outputs /ws
Low

The one that counts is the file write. ComfyUI's experimental dataset "Save" nodes take a free-text folder_name

and join it straight onto the output directory: os.path.join(get_output_directory(), folder_name)

at nodes_dataset.py:255

, with no containment check. Then they os.makedirs

it and write. An absolute path or a ..

chain walks out of output/

. The vector is the one ComfyUI's SECURITY.md

names as in scope: a workflow built from nothing but built-in nodes, the kind people share as JSON and bake into PNGs, writes a file wherever the author chose the moment you load and run it.

A two-node graph is the whole exploit:

curl -s -X POST http://127.0.0.1:8188/prompt -d '{"prompt":{
  "1":{"class_type":"EmptyImage","inputs":{"width":32,"height":32,"batch_size":1,"color":65280}},
  "2":{"class_type":"SaveImageDataSetToFolder",
       "inputs":{"images":["1",0],"folder_name":"/tmp/comfyui_live_escape_abs","filename_prefix":"pwn"}}}}'

I ran it against a fresh 0.22.0 (clean git clone

and pip install

, --cpu

, bound to loopback, no extra flags). The server accepted the graph and wrote the file outside its sandbox. Its own log is the receipt:

[INFO] Saved 1 images to /tmp/comfyui_live_escape_abs.
[INFO] Saved 1 images to …/comfyui-live/output/../../../../../tmp/comfyui_live_escape_rel.

Absolute paths and ..

chains both land. The control is what makes it a bug and not a feature: a standard SaveImage

node handed the same traversal errors out and never creates the directory. It routes through folder_paths.get_save_image_path()

, which raises "outside the output folder." The dataset Save nodes just omit the guard their mainstream siblings have. The attacker picks the directory. The filename is fixed and the bytes are a PNG shaped with EmptyImage

, which is still enough to drop a file into an autostart or config path the server user can write.

It scores Medium. There is no remote, no-interaction version; it needs you to load and run the attacker's workflow on your own box. The fix is the guard the siblings already use, +19/−4

in one file. I filed it as a GitHub security advisory.

The image-read traversal is the same root-cause mistake: an experimental endpoint that forgot the containment its siblings (/view

, uploads, user data) all have. This endpoint is bounded. It leaks images plus a yes/no file-existence oracle, not arbitrary text, and the cross-origin browser path is blocked by ComfyUI's default middleware. So from this sweep I filed only the write and set the read aside. That call aged badly. The read-traversal class is real enough that a sibling LoadImage

version was already public, and a later round of grinding turned up a read in the same class that returns any file byte-for-byte. ComfyUI has since contained the shared helper both of them ran through, on 3 July 2026, and published the LoadImage

traversal as GHSA-rvxv-29p8-pxgq

on 15 July. That one is the strongest finding in the whole audit, filed and since fixed upstream. I wrote it up separately: Reading Any File in ComfyUI.

The pickle finding is the honest walk-back. LoadTrainingDataset

calls torch.load

without weights_only

, reachable through the unauthenticated /prompt

executor with no operator action. For a while it looked like a clean two-request remote-code-execution chain: upload a malicious pickle, then submit the graph that loads it. Then I checked what pip install torch

resolves to. It pulls the latest wheel, where weights_only=True

is the default and the payload is refused. So on a default install it is latent, not exploitable; a working exploit needs a stale or deliberately pinned torch<2.6

.

The lead I killed #

The one I most wanted to be real was the math node. ComfyUI's MathExpression

evaluates a workflow-supplied string through simple_eval

, and workflows travel constantly as JSON files and baked into PNGs from untrusted sources. That is untrusted input straight into an evaluator, no misconfiguration required. I ran all eight of the well-known simpleeval

sandbox escapes through the exact call ComfyUI makes. Every one was refused, both on the version a fresh install pulls and on a years-old release. It is a fragile design, resting on one general-purpose sandbox continuing to hold, but it is not a hole today, so it came off the list.

What I filed, and what I'd send along #

I filed one advisory. The file write is the single finding that crosses ComfyUI's own line, a workflow of built-in nodes writing outside the expected directories, so that is the one I reported, with a few-line fix.

The rest is a hardening list rather than advisories: the image-read traversal (bounded at this endpoint, though the class later produced a filed bug, linked above), the pickle path (needs a stale torch

), and the Manager's admin-and-SSRF gaps (real, but not code execution). The most useful non-code thing for the maintainers is documentation: say plainly that multi-user is not authentication, that the Manager's default security level allows administrative actions, and that ComfyUI assumes a trusted operator and should not be exposed to an untrusted network.

Source was read but not modified, on Comfy-Org/ComfyUI and ComfyUI-Manager at their current main. Severities are my own estimates. The file-write finding is filed as a GitHub security advisory; the live findings were reproduced against a fresh 0.22.0 install on loopback.

Disclosure timeline: audit run and findings drafted 1 June 2026 against ComfyUI main (70a2e1a) and ComfyUI-Manager. The file-write finding was reported to Comfy Org directly. The stronger file-read finding from the later rounds was reported as a GitHub security advisory on 1 June 2026, and ComfyUI shipped path containment for the shared helper on 3 July 2026 (96e0e35), hardened 2 August (41a3e16). Published 11 August 2026. Reproduction details throughout are given against 0.22.0.

── more in #ai-tools 4 stories · sorted by recency
── more on @comfyui 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/one-bug-made-the-cut…] indexed:0 read:8min 2026-08-11 ·