Back to skill

Security audit

ComfyUI Automation

Security checks for vulnerabilities and agentic risk

Overview

The ComfyUI skill is coherent, but it needs Review because it can install unpinned third-party code and models without clear user approval or provenance controls.

Install only in an isolated workspace or container. Pin ComfyUI and each custom node to reviewed commits, approve every new custom-node repository manually, and verify model sources and checksums before downloading large files.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T08 · Insecure Dependencies

Error
Location
SKILL.md:25
Finding

Unpinned Third-Party Components Are Downloaded and Executed

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 25-30 and line 80
Vulnerability Type: Supply-chain compromise through unpinned dependencies and custom nodes
Risk Level: High

Vulnerable Code

bash
cd /root/.openclaw/workspace
git clone https://github.com/comfyanonymous/ComfyUI.git
cd ComfyUI
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt

The skill also directs the agent to install dynamically selected custom nodes:

text
- **Missing Nodes:** If the API returns an error about a missing class/node, locate the corresponding Custom Node repository, clone it into `ComfyUI/custom_nodes/`, and `pip install -r requirements.txt` inside its folder using the `venv`.

Technical Analysis

The installation procedure clones the current default branch of ComfyUI without pinning it to a reviewed commit. It then installs dependencies from the repository's current requirements.txt without requiring package hashes.

The missing-node procedure is more exposed because it instructs the agent to locate and clone a repository based on a workflow error. No repository allowlist, required commit hash, signature verification, dependency hash verification, or manual review requirement is defined. A repository selected this way can contain malicious Python dependencies or custom-node code that ComfyUI imports and executes.

Use of a virtual environment prevents direct modification of the operating system's Python installation, but it does not sandbox the installed code. Processes running from the virtual environment ordinarily retain the filesystem, network, and user-account privileges of the agent that launches them.

Attack Path

  1. An attacker supplies a ComfyUI workflow that references an unavailable custom node.
  2. ComfyUI reports that the corresponding node class is missing.
  3. Following the skill instructions, the agent searches f ...[truncated 1249 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin ComfyUI to a reviewed full commit hash and check out that exact commit after cloning.
  2. Maintain an allowlist mapping supported custom-node classes to approved repository URLs and reviewed commit hashes.
  3. Do not discover and install arbitrary repositories solely from node names or search results.
  4. Require dependency lock files with exact versions and cryptographic hashes, and install with hash enforcement such as pip install --require-hashes.
  5. Verify repository provenance and review Python modules, package manifests, installation hooks, and dependency changes before installation.
  6. Separate installation from workflow execution and require explicit approval before adding a new custom node.
  7. Run ComfyUI under a dedicated least-privileged account or container with narrowly scoped filesystem access, restricted network access, no host credentials, and no access to unrelated workspaces.
  8. Record the repository URL, commit hash, dependency hashes, and review status for every installed component.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/analyze_models.py:35
Finding

Workflow-Controlled Model Paths Permit Filesystem Existence Probing

Content
View full analysis

Vulnerability Details

File Location: scripts/analyze_models.py, lines 35-47
Vulnerability Type: Path traversal and absolute-path injection
Risk Level: Low

Vulnerable Code

python
            model_filename = None
            for key, val in inputs.items():
                if isinstance(val, str) and (val.endswith(".safetensors") or val.endswith(".ckpt") or val.endswith(".pt")):
                    model_filename = val
                    break
            
            if model_filename:
                # Resolve the absolute path
                model_path = os.path.join(comfy_dir, "models", target_dir, model_filename)
                
                if not os.path.exists(model_path):
                    missing_models.append((class_type, model_filename, target_dir))

Technical Analysis

model_filename is obtained directly from an untrusted workflow JSON value. The code accepts it based only on a filename suffix and passes it to os.path.join without rejecting absolute paths, resolving traversal components, or verifying that the final path remains beneath the expected model directory.

If model_filename is absolute, Python's os.path.join discards the preceding ComfyUI model directory components. A relative value containing ../ components can similarly escape the expected directory after filesystem path resolution.

The subsequent os.path.exists call therefore tests an attacker-selected filesystem path. Its result is externally distinguishable: nonexistent paths are printed under MISSING MODELS DETECTED and cause exit status 2, while paths that exist are omitted and may produce the successful message and exit status 0.

The suffix requirement limits directly tested names to paths ending in .safetensors, .ckpt, or .pt, but it does not enforce containment. This behavior is an existence oracle; the script does not read or return file contents.

Attack Path

...[truncated 1323 chars]

Remediation
View remediation

Remediation Suggestions

  1. Reject absolute model paths.
  2. Resolve the expected model directory and candidate path to canonical absolute paths before testing existence.
  3. Verify that the resolved candidate remains beneath the loader-specific model directory.
  4. Reject values containing traversal components rather than silently normalizing them.
  5. Where ComfyUI supports model subdirectories, permit only validated relative paths beneath the approved root.
  6. Avoid returning unnecessary path details for untrusted workflow data.

Example hardening approach:

python
from pathlib import Path

base = (Path(comfy_dir) / "models" / target_dir).resolve()
supplied = Path(model_filename)

if supplied.is_absolute() or ".." in supplied.parts:
    raise ValueError("Model filename must be a contained relative path")

candidate = (base / supplied).resolve()
if not candidate.is_relative_to(base):
    raise ValueError("Model path escapes the expected model directory")

if not candidate.exists():
    missing_models.append((class_type, model_filename, target_dir))

If compatibility with Python versions before 3.9 is required, perform containment validation with os.path.commonpath while handling path and drive errors explicitly.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill instructs use of filesystem access and shell commands but declares no explicit tool scope or permissions boundary. That makes the skill harder to constrain safely and increases the chance an agent will perform workspace-modifying actions without clear authorization or policy enforcement.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill directs cloning a repository and installing Python dependencies into the local workspace without any user-facing warning or approval checkpoint. This can alter the environment, execute untrusted package install scripts, and create supply-chain risk if an agent follows the instructions automatically.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill instructs downloading model files from external sources into the filesystem without warning about large downloads, disk usage, provenance, or integrity checks. This creates both operational risk and a supply-chain avenue for introducing malicious or unsafe artifacts into the environment.

Content

No source excerpt is available for this finding.

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

Scanner excerpt · SKILL.md (reported line 72)May include surrounding context.

md
# 3. Submit to API
payload = json.dumps({"prompt": workflow}).encode('utf-8')
req = urllib.request.Request("http://127.0.0.1:8188/prompt", data=payload)
req.add_header('Content-Type', 'application/json')
res = json.loads(urllib.request.urlopen(req).read())
print(f"Prompt queued with ID: {res['prompt_id']}")

Static analysis

No suspicious patterns detected.