Like leaving a loaded gun on a table, but the table is in a locked room most people never open the door to
CVE-2026-68771 is an unsafe pickle deserialization flaw in ComfyUI v0.23.0's LoadTrainingDataset node. The LoadTrainingDataset.execute method calls torch.load() without weights_only=True on user-supplied .pkl shard files. An attacker uploads a crafted shard_*.pkl via the unauthenticated POST /upload/image endpoint, then queues a workflow via POST /prompt referencing that file. Python's pickle.__reduce__ fires during deserialization, granting arbitrary code execution as the ComfyUI process user. Affected: ComfyUI v0.23.0 and likely earlier versions using the same code path. Fixed in commit 94ee49b (PR #14543, merged 2026-06-18) by adding weights_only=True.
The vendor CVSS of 9.8 (AV:N/AC:L/PR:N/UI:N) is technically accurate for the protocol but overstates real-world risk because ComfyUI binds to 127.0.0.1 by default. An attacker cannot reach it without the operator explicitly passing --listen 0.0.0.0 or proxying it. Censys data shows roughly 1,000–2,800 internet-facing instances globally — a small fraction of total installs. That said, those exposed instances have zero authentication and are actively being targeted by cryptomining botnets (GHOST campaign, NadMesh). For the population that *is* exposed, this is a trivial, weaponizable, no-auth RCE. The vendor’s CRITICAL label is fair for that slice; for the majority on localhost, it’s noise. We split the difference at HIGH.
4 steps from start to impact.
Discover exposed ComfyUI instance
title:"ComfyUI") or Censys to find ComfyUI instances bound to 0.0.0.0 on port 8188. Censys reports ~1,000+ live, unauthenticated instances. NadMesh and GHOST campaigns automate this at scale.- ComfyUI instance is bound to a non-localhost address (operator used
--listen) - No reverse proxy or firewall blocking port 8188
- ComfyUI defaults to
127.0.0.1— most instances are not reachable - Enterprise firewalls typically block non-standard inbound ports
Upload malicious pickle shard
POST /upload/image request with a file named shard_0.pkl containing a crafted Python pickle payload. The __reduce__ method in the pickle object specifies an os.system() or subprocess.Popen() call. No authentication is required. The upload endpoint does not validate file type beyond the extension.- Unauthenticated access to the ComfyUI HTTP API
- Upload endpoint accepts
.pklfiles
- If a WAF is in front, it might block binary uploads or unusual extensions
- ComfyUI-Manager in
normal-security mode restricts some operations on public-facing instances, but does not block uploads
.pkl uploads to image endpoints; file-integrity monitoring on the ComfyUI input directoryQueue workflow referencing the shard
POST /prompt request containing a workflow JSON that includes a LoadTrainingDataset node pointing to the directory containing the uploaded malicious shard file. This is a normal, expected API call — ComfyUI has no workflow validation or sandboxing at this layer.- Attacker knows (or guesses) the upload path for shard files
- LoadTrainingDataset node is available in the ComfyUI build
- The LoadTrainingDataset node must be present; it ships as a built-in extra in
comfy_extras/nodes_dataset.py
POST /prompt requests from external IPs; anomalous workflow graph analysisArbitrary code execution via torch.load
torch.load() deserializes the attacker-controlled .pkl file without weights_only=True. Python’s pickle protocol invokes __reduce__, executing arbitrary code as the ComfyUI process user. The attacker gains a shell with whatever privileges the ComfyUI process runs under — typically a regular user, but on GPU workstations this often means access to cloud credentials, model weights, and training data.- ComfyUI is running v0.23.0 or earlier unpatched code
- PyTorch processes the pickle without safe-loading restrictions
- On PyTorch >= 2.6 with
weights_only=Trueas default, this would be blocked — but the code explicitly callstorch.load()without the flag
python -> bash -> curl)The supporting signals.
| In-the-wild exploitation | Yes, indirectly. The GHOST campaign (March 2026) and NadMesh botnet (July 2026) actively target exposed ComfyUI instances for cryptomining and proxy botnet recruitment. These campaigns use custom-node code execution rather than this specific CVE, but the attack surface (unauthenticated /prompt + code execution) is identical. |
|---|---|
| Proof of concept | No dedicated public PoC repository found for CVE-2026-68771 specifically. However, crafting a malicious pickle payload is trivial and well-documented — dozens of generic torch.load pickle RCE PoCs exist on GitHub. Weaponization is copy-paste level. |
| EPSS | 0.00623 (low, ~top 15%). Reflects the niche install base rather than exploit difficulty. |
| KEV status | Not listed on CISA KEV as of 2026-08-02. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (9.8). Network-reachable, no auth, no user interaction, full CIA impact. CVSS 4.0: 9.3. The vector is accurate *if* the instance is network-exposed. |
| Affected versions | ComfyUI v0.23.0 and likely all prior versions shipping comfy_extras/nodes_dataset.py with the unguarded torch.load() call. |
| Fixed version | Commit 94ee49b merged 2026-06-18 into master. No tagged release version confirmed; users on master or nightly builds after that date are patched. |
| Scanning / exposure data | Censys: ~1,000+ unauthenticated ComfyUI instances internet-facing (after filtering honeypots). Shodan title:"ComfyUI" returns ~2,800 results, ~800 behind login pages. Censys blog |
| Disclosure date | 2026-07-31 (NVD published) |
| Reporter | Bofei Chen |
noisgate verdict.
The single most decisive factor is the default localhost-only bind address — the vast majority of ComfyUI installations are unreachable from the network, collapsing the AV:N assumption in the vendor’s 9.8 score. For the ~1,000 globally exposed instances that *are* reachable, this remains a trivial, weaponizable, no-auth RCE with active campaign interest, which floors the verdict at HIGH.
Why this verdict
- Default bind address caps reachability. ComfyUI listens on
127.0.0.1:8188out of the box. The CVSS AV:N score assumes network reachability that does not exist in default deployments. This is the largest single friction factor and justifies moving from CRITICAL to HIGH. - No authentication when exposed. For the subset of instances where an operator has passed
--listen 0.0.0.0, there is zero authentication on both/upload/imageand/prompt. The chain is fully unauthenticated and requires no user interaction. This prevents a further downgrade to MEDIUM. - Active campaign interest in ComfyUI. The GHOST and NadMesh campaigns demonstrate that threat actors are actively scanning for and exploiting exposed ComfyUI instances. While they use custom-node code execution rather than this specific CVE, the identical attack surface means this CVE is immediately adoptable into existing tooling.
- Role multiplier: ComfyUI is an AI image-generation workstation tool. (a) *Low-value role*: hobbyist GPU desktop — majority of installs, blast radius is one workstation. (b) *Typical role*: team ML workstation in an enterprise — may hold cloud credentials, model IP, training data. Compromise = host-level, potentially pivoting to cloud accounts. (c) *High-value role*: ComfyUI embedded in CI/CD or model-training pipelines — rare but possible; blast radius could reach supply-chain for AI model artifacts. ComfyUI is NOT a canonical high-value-role component (it is not an IdP, hypervisor, DC, or network edge device). <1% of installs occupy a high-value role. No floor elevation beyond HIGH is warranted.
Why not higher?
CRITICAL would require either KEV listing, canonical high-value-role deployment (ComfyUI is a workstation tool, not infrastructure), or default network exposure. None apply. The default localhost bind means >95% of installations are simply unreachable for this attack vector, and the ~1,000 exposed instances represent a narrow global population.
Why not lower?
MEDIUM would understate the risk for the exposed population. The chain is fully unauthenticated, zero-click, trivially weaponizable with off-the-shelf pickle payloads, and threat actors are *already scanning for ComfyUI instances*. Active campaign interest plus no-auth RCE on exposed hosts demands HIGH at minimum.
What to do — in priority order.
- Bind ComfyUI to localhost only — Ensure ComfyUI is started without
--listenor explicitly with--listen 127.0.0.1. This is the default and eliminates remote attack surface entirely. Verify within noisgate mitigation SLA (30 days for HIGH). Audit all ComfyUI launch scripts, systemd units, and Docker compose files for--listen 0.0.0.0. - Place a reverse proxy with authentication in front of any intentionally exposed instance — If remote access is required, use nginx/Caddy with OAuth2 Proxy, SSO, or HTTP basic auth. This converts the unauthenticated attack surface into an authenticated one. Deploy within 30 days.
- Block
.pklfile uploads at WAF or reverse proxy — Add a WAF rule to rejectPOST /upload/imagerequests where the filename ends in.pkl,.pickle, or.pt. This breaks the upload step of the chain without affecting normal image uploads. - Update to post-fix commit — Pull ComfyUI master at or after commit
94ee49b(2026-06-18). The fix is a one-line change addingweights_only=Truetotorch.load()incomfy_extras/nodes_dataset.py. Apply within the noisgate remediation SLA of 180 days for HIGH. - Network-segment GPU workstations — Place ComfyUI hosts in a dedicated VLAN with egress filtering. Restrict outbound to package repos and model registries only. This limits post-exploitation lateral movement and C2 callback.
- EDR process-tree detection alone — pickle deserialization executes within the Python process, so the initial code execution may not spawn a child process. Fileless payloads (in-memory reverse shells, Python-native C2) bypass process-tree heuristics.
- PyTorch version upgrade alone — even on PyTorch >= 2.6,
weights_onlydefaults vary by minor version and the vulnerable code explicitly passes no flag, falling back to unsafe behavior. The application code must be patched. - ComfyUI-Manager security modes — the
normal-security level restricts custom node installation on public-facing instances but does NOT block the/upload/imageor/promptendpoints used in this chain.
Crowdsourced verification payload.
Run this on each host where ComfyUI is installed. It checks the nodes_dataset.py source for the patched weights_only=True parameter and verifies the listen address. Requires read access to the ComfyUI installation directory. Example: bash check_cve_2026_68771.sh /opt/ComfyUI
#!/usr/bin/env bash\n# CVE-2026-68771 checker for ComfyUI unsafe deserialization\n# Usage: bash check_cve_2026_68771.sh /path/to/ComfyUI\n# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN\n\nset -euo pipefail\n\nCOMFY_DIR=\"${1:-}\"\nif [ -z \"$COMFY_DIR\" ]; then\n echo \"Usage: $0 /path/to/ComfyUI\"\n exit 2\nfi\n\nTARGET_FILE=\"${COMFY_DIR}/comfy_extras/nodes_dataset.py\"\n\nif [ ! -f \"$TARGET_FILE\" ]; then\n echo \"UNKNOWN - File not found: $TARGET_FILE\"\n echo \"ComfyUI may not have the LoadTrainingDataset node installed.\"\n exit 2\nfi\n\n# Check if torch.load calls include weights_only=True\nif grep -q 'torch\\.load' \"$TARGET_FILE\"; then\n # Count torch.load calls without weights_only=True\n UNSAFE_CALLS=$(grep 'torch\\.load' \"$TARGET_FILE\" | grep -cv 'weights_only' || true)\n if [ \"$UNSAFE_CALLS\" -gt 0 ]; then\n echo \"VULNERABLE - CVE-2026-68771\"\n echo \"Found $UNSAFE_CALLS torch.load() call(s) without weights_only=True in $TARGET_FILE\"\n grep -n 'torch\\.load' \"$TARGET_FILE\" | grep -v 'weights_only'\n \n # Also check listen address in running process\n if pgrep -f 'comfyui\\|main.py.*--listen' > /dev/null 2>&1; then\n LISTEN_ADDR=$(ps aux | grep -E 'comfyui|main.py' | grep -oP '\\-\\-listen\\s+\\K[\\d.]+' || echo 'localhost (default)')\n echo \"Listen address: $LISTEN_ADDR\"\n if [ \"$LISTEN_ADDR\" = \"0.0.0.0\" ]; then\n echo \"WARNING: Instance is bound to all interfaces - REMOTELY EXPLOITABLE\"\n fi\n fi\n exit 1\n else\n echo \"PATCHED - CVE-2026-68771\"\n echo \"All torch.load() calls in $TARGET_FILE include weights_only parameter.\"\n exit 0\n fi\nelse\n echo \"UNKNOWN - No torch.load calls found in $TARGET_FILE\"\n exit 2\nfiIf you remember one thing.
--listen 0.0.0.0 and no reverse-proxy authentication is a live, unauthenticated RCE target that active botnets are already scanning for. Per the noisgate mitigation SLA for HIGH, lock down network exposure within 30 days: rebind to localhost or put an authenticating reverse proxy in front. Per the noisgate remediation SLA, update to a ComfyUI build at or after commit 94ee49b within 180 days. If you have *zero* ComfyUI installations, document that finding and move on. If any instance is internet-facing without auth, treat it as an emergency and patch immediately regardless of SLA — the GHOST and NadMesh campaigns are actively converting exposed ComfyUI boxes into cryptomining rigs.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.