A janky filename parser in an AI workflow toy lets a logged-in user peek at files they shouldn't
CVE-2026-13493 lives in backend/controller/conversation_api.py of AIDC-AI ComfyUI-Copilot — a third-party custom node that bolts an LLM assistant onto the popular ComfyUI image-generation framework. The Workflow Checkpoint Restore Handler does improper control of resource identifiers (CWE-99): an authenticated request can manipulate a checkpoint/workflow identifier so the handler dereferences a resource the caller shouldn't reach. CVSS vector C:L/I:N/A:N confirms the impact ceiling: read-only, partial confidentiality, no integrity or availability hit. All versions 2.0.0 through 2.0.28 are affected; as of disclosure (2026-06-28) PR #150 sits unmerged, so no fixed release yet.
The vendor's LOW (3.1) rating matches reality. ComfyUI-Copilot is a hobbyist/creator-tier plugin layered on top of ComfyUI — itself rarely Internet-exposed and almost never deployed in regulated enterprise data paths. The attacker must already be an authenticated user of a Copilot instance, the attack complexity is high (AC:H), EPSS is 0.00232 (~bottom quartile), KEV is silent, and the worst outcome is leaking workflow metadata or adjacent file content — not RCE, not auth bypass, not lateral movement. There is no role-multiplier case where this component sits on a domain controller, hypervisor, or identity provider. Treat as a tracked backlog item, not an incident.
4 steps from start to impact.
Locate a reachable ComfyUI-Copilot instance
- Network reachability to the Copilot backend HTTP endpoint
- Target running ComfyUI-Copilot ≤ 2.0.28
- ComfyUI is overwhelmingly deployed on localhost or LAN by individual artists/researchers
- Copilot is an opt-in custom node, not bundled with ComfyUI core
- Most enterprise GenAI stacks use SDXL/Flux behind managed APIs, not ComfyUI plugins
comfyui + path probe /copilot works but yields a tiny pool; no vendor signature for this CVE yetObtain authenticated session
PR:L means the attacker must already hold a low-privileged authenticated session on the Copilot backend. In practice that means a stolen API token, a shared workspace credential, or a deployment that wired Copilot to internal SSO without scoping.- Valid user credentials, API key, or hijacked session cookie
- Knowledge of the Copilot auth flow
- ComfyUI itself has no built-in auth — many Copilot deployments either run open on LAN (no auth flow at all) or are gated by a reverse proxy that the attacker must also defeat
- Public exposure without auth is a separate misconfiguration class, not this CVE
/conversation_api routesCraft malformed checkpoint identifier
conversation_api.py accepts without normalization. CWE-99 ID-confusion classes typically resolve to reading a file or session resource the caller wasn't authorized to access.- Working knowledge of the checkpoint restore endpoint schema (public, in repo)
- Ability to send authenticated POST/GET to the affected route
AC:H— the vendor flagged exploit complexity high, implying non-obvious payload shape and possibly race/state requirements- PoC is public but quality and reliability are unverified
Read unauthorized resource
C:L: partial, not full disclosure; I:N/A:N rules out write or denial-of-service.- Step 3 payload accepted by handler
- Target resource readable by the Copilot service account
- Most Copilot installs run as an unprivileged user with read access only to the workflow/checkpoint directory
- No path to credentials, secrets, or host filesystem beyond what the process already touches
The supporting signals.
| In-the-wild exploitation | None observed. No campaigns, no honeypot hits, no vendor IR notes as of 2026-06-30. |
|---|---|
| Proof-of-concept | Public PoC referenced in the disclosure (GitHub issue #149); reliability and weaponization quality unverified. |
| EPSS | 0.00232 — roughly the ~50th percentile; FIRST's model expects effectively zero exploitation activity over the next 30 days. |
| KEV status | Not listed. CISA has not added CVE-2026-13493 to the Known Exploited Vulnerabilities catalog. |
| CVSS vector | CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N → network-reachable but high-complexity, authenticated, read-only partial disclosure. |
| Affected versions | AIDC-AI ComfyUI-Copilot 2.0.0 through 2.0.28 (all releases prior to a forthcoming fix). |
| Fixed version | None released as of 2026-06-30. Fix is proposed in PR #150, awaiting maintainer merge. |
| Exposure data | Shodan/Censys queries for ComfyUI instances return a few thousand hosts globally; the Copilot custom node is an opt-in subset, and almost none are enterprise-managed. Enterprise blast radius effectively <0.01% of typical Fortune 1000 fleets. |
| Disclosure | Published 2026-06-28 via GitHub Security Advisory GHSA-CJXX-6MF8-HQMW. |
| Reporter | Disclosed via the AIDC-AI ComfyUI-Copilot project GitHub issue tracker; no named external researcher in the advisory. |
noisgate verdict.
The decisive factor is role multiplier — there isn't one: ComfyUI-Copilot is a hobbyist generative-art plugin, never deployed as identity, hypervisor, backup, CA, or kernel-security infrastructure, and impact is capped at authenticated partial read (C:L/I:N/A:N). Vendor LOW is correct and we hold it at LOW with a marginal downward nudge to 2.8 to reflect the absence of a released patch.
Why this verdict
- Authentication required (PR:L): The attacker must already hold a valid session on the Copilot backend, which by itself filters out the unauthenticated drive-by class.
- High attack complexity (AC:H): Vendor and CVSS both call exploitation difficult — non-trivial payload shape, possibly state-dependent.
- Impact capped at C:L / I:N / A:N: Best-case attacker outcome is reading workflow JSON or adjacent file content the Copilot process can already see. No RCE, no integrity, no DoS.
- Role multiplier: low-value role only. ComfyUI-Copilot runs in the (a) low-value-role bucket — creator workstation or isolated GenAI sandbox. There is no (c) high-value-role deployment pattern: it is not on DCs, identity providers, hypervisors, backup, CA, EDR, or supply-chain registries. Floor stays at LOW.
- Installed-base evidence: Shodan-visible ComfyUI footprint is a few thousand worldwide, and the Copilot custom node is an opt-in subset — well under 1% of enterprise estates have it at all, and effectively 0% of regulated/identity-tier hosts.
- EPSS 0.00232 + no KEV + no observed exploitation: All three exploit-prediction signals align with the LOW bucket.
Why not higher?
Upgrading to MEDIUM would require either a credible mass-exploitation signal (none — EPSS bottom-quartile, no KEV, no campaigns) or a role-multiplier story where the affected component lands on a high-value asset (impossible — Copilot is a creator-tier plugin). The impact ceiling itself (C:L/I:N/A:N) caps the realistic damage well below what MEDIUM implies.
Why not lower?
We didn't push to IGNORE because a public PoC exists, no patched version has shipped yet (PR #150 unmerged), and the vulnerability is reachable over the network by any low-privileged user — so a multi-tenant Copilot deployment with sloppy auth scoping could genuinely leak another tenant's workflow. That keeps it in the tracked-backlog bucket, not the document-and-forget bucket.
What to do — in priority order.
- Inventory ComfyUI-Copilot installs — Grep your AI/ML asset register and developer workstation MDM data for ComfyUI custom-node directories containing
ComfyUI-Copilot. Most orgs will return zero hits; the few that do are typically R&D or marketing creative teams. No mitigation SLA applies at LOW — handle within the noisgate remediation SLA of 365 days. - Block Copilot backend from untrusted networks — Bind the ComfyUI/Copilot HTTP listener to localhost or place it behind an authenticating reverse proxy with per-user scoping. This kills the network-reachability prerequisite entirely for any install that doesn't strictly need remote use.
- Scope service account file access — Run ComfyUI/Copilot as an unprivileged user whose filesystem read scope is restricted to the model/workflow directory only. Caps the worst-case CWE-99 read to data the user already has rights to.
- Track PR #150 and pin to the fixed release — Subscribe to AIDC-AI/ComfyUI-Copilot releases. When the fix merges and a 2.0.29+ release ships, upgrade in the same maintenance window you already use for creative-tools — no out-of-band action required.
- Generic WAF deployments — most enterprises don't proxy internal AI-art tooling through a WAF, and the payload shape (resource-identifier manipulation in a custom JSON endpoint) is unlikely to match default OWASP CRS rules.
- EDR alerts — there is no host-level execution to detect; the attack is an authenticated HTTP request returning a file read inside the Copilot process.
- MFA — does not help once the attacker holds a valid session/token, which is the assumed starting state.
- Network egress DLP — workflow JSON is small, mundane-looking traffic; DLP signatures will not distinguish a legitimate Copilot response from a CVE-2026-13493 leak.
Crowdsourced verification payload.
Run on any host that may have ComfyUI-Copilot installed (developer workstation, GPU server, AI sandbox). Invoke as python check_cve_2026_13493.py /path/to/ComfyUI/custom_nodes — defaults to scanning the current directory if no path given. Needs only read access to the ComfyUI custom_nodes directory; no elevated privileges required.
#!/usr/bin/env python3
# check_cve_2026_13493.py
# Detects vulnerable installs of AIDC-AI/ComfyUI-Copilot (<= 2.0.28).
# Exit codes: 0=PATCHED/NotInstalled, 1=VULNERABLE, 2=UNKNOWN
import os, re, sys, json
from pathlib import Path
VULN_MAX = (2, 0, 28) # inclusive: every version <= 2.0.28 is affected
def parse_version(v):
m = re.match(r"(\d+)\.(\d+)\.(\d+)", v.strip().lstrip("vV"))
return tuple(int(x) for x in m.groups()) if m else None
def find_copilot_roots(base):
roots = []
for p in Path(base).rglob("ComfyUI-Copilot"):
if p.is_dir():
roots.append(p)
return roots
def extract_version(root):
# Try common locations in order.
candidates = [
root / "pyproject.toml",
root / "setup.py",
root / "package.json",
root / "__init__.py",
root / "VERSION",
]
for c in candidates:
if not c.exists():
continue
try:
text = c.read_text(errors="ignore")
except Exception:
continue
if c.name == "package.json":
try:
v = json.loads(text).get("version")
if v: return v
except Exception:
pass
m = re.search(r"version\s*=\s*[\"']([0-9]+\.[0-9]+\.[0-9]+)", text, re.I)
if m: return m.group(1)
m = re.search(r"__version__\s*=\s*[\"']([0-9]+\.[0-9]+\.[0-9]+)", text)
if m: return m.group(1)
return None
def main():
base = sys.argv[1] if len(sys.argv) > 1 else "."
if not Path(base).exists():
print(f"UNKNOWN: path not found: {base}")
return 2
roots = find_copilot_roots(base)
if not roots:
print("PATCHED: ComfyUI-Copilot not installed under", base)
return 0
worst = 0
for r in roots:
v = extract_version(r)
if not v:
print(f"UNKNOWN: {r} — version not determinable")
worst = max(worst, 2)
continue
parsed = parse_version(v)
if parsed is None:
print(f"UNKNOWN: {r} — version string {v!r} unparseable")
worst = max(worst, 2)
continue
status = "VULNERABLE" if parsed <= VULN_MAX else "PATCHED"
print(f"{status}: {r} (version {v})")
if status == "VULNERABLE":
worst = max(worst, 1)
return worst
if __name__ == "__main__":
sys.exit(main())
If you remember one thing.
Sources
- Vulnerability-Lookup: CVE-2026-13493
- Vulnerability-Lookup: GHSA-CJXX-6MF8-HQMW
- AIDC-AI/ComfyUI-Copilot GitHub repository
- ComfyUI-Copilot issue #149 (disclosure)
- ComfyUI-Copilot PR #150 (proposed fix)
- ComfyUI-Copilot releases page
- ComfyUI-Copilot project site
- MITRE CWE-99: Improper Control of Resource Identifiers
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.