Back to skill

Security audit

ComfyUI Bridge

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent local image-generation purpose, but its queued background delivery and shell fallback create real privacy and command-execution risks.

Install only if you are comfortable with sensitive images being sent to the configured bridge and potentially queued on disk. Use a trusted local or authenticated bridge, avoid plaintext non-loopback HTTP for private or face images, disable or tightly control the queue daemon and iMessage delivery, verify the iMessage recipient, and do not run the queue processor until the shell fallback and queue path validation are fixed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/queue_processor.py:101
Finding

Shell Command Injection Through Queue-Controlled iMessage Chat ID

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/queue_processor.py:171
Finding

Queue Processor Permits Arbitrary File Reads, Network Uploads, and File Overwrites

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/comfyui_generate.py:107
Finding

Sensitive Biometric Images Are Transmitted Over Plaintext HTTP and Retained Indefinitely

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
SKILL.md:32
Finding

Installation and Runtime Dependencies Are Retrieved From Mutable, Incompletely Pinned Sources

Content
View full analysis
=3.10" # dependencies = [ # "httpx>=0.25.0", # ] # /// ``` ### Technical Analysis The documented installation process retrieves the current default branch of an external repository and installs its current dependency graph without pinning a reviewed commit, signed release, or artifact digest. The generator also permits any future `httpx` version greater than or equal to `0.25.0`. The repository URL matches the declared project homepage, and the audit found no evidence of typosquatting or an intentionally malicious package. The risk is that the effective code executed by future users can change after this Skill package has been reviewed. This is a supply-chain reproducibility and integrity weakness rather than evidence that the current upstream source is malicious. ### Attack Path 1. The upstream repository, maintainer account, package release process, or transitive dependency is compromised. 2. A user follows the installation instructions after the compromise. 3. `git clone` retrieves the modified default branch, or package resolution selects a compromised future release. 4. The user installs and executes the changed code. 5. The compromised code receives the privileges and data available to the bridge host, including uploaded images and local model access. ### Impact Assessment Impact depends on the privileges of the account running installation and the bridge server. A compromised dependency or ...[truncated 411 chars]
Remediation
View remediation
``` 2. Publish and verify signed releases or checksums for installation artifacts. 3. Pin exact direct and transitive dependency versions in a lockfile. 4. Use package hashes where supported, such as `pip --require-hashes`. 5. Replace the open-ended `httpx>=0.25.0` constraint with a reviewed exact version or lockfile-managed version. 6. Automate dependency vulnerability scanning and periodically review updates before changing pins. 7. Run the bridge under a dedicated low-privilege service account to reduce the impact of a future supply-chain compromise. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (36)

Tainted flow: 'BRIDGE_URL' from os.environ.get (line 43, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The bridge URL is taken directly from an environment variable and used for network requests without validation. In this skill's context, that means whoever controls the environment can redirect all prompts, uploaded images, and downloaded results to an unintended host, creating SSRF-like behavior and data exfiltration risk, especially because the tool handles local images and face data.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 351)May include surrounding context.

python
# Health check first
    try:
        r = httpx.get(f"{BRIDGE_URL}/health", timeout=5)
        r.raise_for_status()
        health = r.json()
        print(f"Bridge online: {BRIDGE_URL}")

Tainted flow: 'download_url' from os.environ.get (line 447, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The script downloads image content from a URL built from the same unvalidated bridge base URL and writes it directly to the requested output path. A malicious bridge destination could return arbitrary content, enabling silent poisoning of outputs and untrusted file writes under the guise of generated media.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 450)May include surrounding context.

python
download_url = f"{BRIDGE_URL}/download/{prompt_id}"
        print(f"Downloading result directly from bridge...")
        try:
            img_resp = httpx.get(download_url, timeout=30)
            img_resp.raise_for_status()
            output_path.write_bytes(img_resp.content)
            downloaded = True

Tainted flow: 'BRIDGE_URL' from os.environ.get (line 43, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Retry download logic again fetches untrusted content from the environment-derived bridge and writes it to disk. This compounds the risk by repeating trust in a potentially attacker-controlled destination and can overwrite the output with arbitrary data.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 496)May include surrounding context.

python
retry_downloaded = False
            if retry_prompt_id:
                try:
                    r2 = httpx.get(f"{BRIDGE_URL}/download/{retry_prompt_id}", timeout=30)
                    r2.raise_for_status()
                    output_path.write_bytes(r2.content)
                    retry_downloaded = True

Tainted flow: 'BRIDGE_URL' from os.environ.get (line 43, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

This POST sends user prompts and generation parameters to a host derived from an untrusted environment variable. In the context of an image-generation bridge, redirection to a malicious endpoint can capture sensitive prompts, metadata, and influence returned content while appearing legitimate to the caller.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 556)May include surrounding context.

python
print(f"Generating image ({mode_str}, model={args.model})...")
    print(f"Prompt: {args.prompt}")
    try:
        r = httpx.post(
            f"{BRIDGE_URL}/generate",
            json=payload,
            timeout=120,

Tainted flow: 'BRIDGE_URL' from os.environ.get (line 43, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

This endpoint uploads a user-supplied local image to the bridge URL from the environment, so a maliciously set destination can exfiltrate local image contents. Because the skill explicitly operates on personal photos and edits, the privacy impact is significant.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 591)May include surrounding context.

python
"seed": str(args.seed),
                    "enhance": str(not args.no_enhance).lower(),
                }
                r = httpx.post(
                    f"{BRIDGE_URL}/img2img",
                    files=files,
                    data=data,

Tainted flow: 'BRIDGE_URL' from os.environ.get (line 43, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
91% confidence
Finding

Faceswap pipeline mode sends source and target face images to a destination controlled by COMFYUI_BRIDGE_URL. Since this mode handles especially sensitive biometric-style face data, an attacker controlling the environment can cause highly sensitive image exfiltration.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 649)May include surrounding context.

python
"restore_visibility": str(args.restore_visibility),
                    "enhanced": str(args.enhanced).lower(),
                }
                r = httpx.post(
                    f"{BRIDGE_URL}/faceswap/pipeline",
                    files=files,
                    data=data,

Tainted flow: 'BRIDGE_URL' from os.environ.get (line 43, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
91% confidence
Finding

This faceswap request uploads face images to an environment-controlled server without host validation. In context, the sensitivity is elevated because the transmitted data includes identifiable facial imagery, making unintended disclosure more serious than generic prompt leakage.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 708)May include surrounding context.

python
"restore_visibility": str(args.restore_visibility),
                    "enhanced": str(args.enhanced).lower(),
                }
                r = httpx.post(
                    f"{BRIDGE_URL}/faceswap",
                    files=files,
                    data=data,

Tainted flow: 'BRIDGE_URL' from os.environ.get (line 43, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

LivePortrait mode uploads portrait images to a host chosen via environment variable, enabling redirection of sensitive personal images to an attacker-controlled service. The skill's LAN/self-hosted positioning makes such hidden redirection more dangerous because users may assume data never leaves the local machine.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 786)May include surrounding context.

python
"rotate_yaw": str(args.yaw),
                    "rotate_roll": str(args.roll),
                }
                r = httpx.post(
                    f"{BRIDGE_URL}/liveportrait",
                    files=files,
                    data=data,

Tainted flow: 'BRIDGE_URL' from os.environ.get (line 43, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Style-transfer mode uploads a reference image to the bridge selected by COMFYUI_BRIDGE_URL. If an attacker can influence that environment variable, the script becomes a convenient exfiltration channel for local image files while the user expects a self-hosted local workflow.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 834)May include surrounding context.

python
"style_weight": str(args.style_weight),
                    "enhance": str(not args.no_enhance).lower(),
                }
                r = httpx.post(
                    f"{BRIDGE_URL}/style-transfer",
                    files=files,
                    data=data,

Tainted flow: 'BRIDGE_URL' from os.environ.get (line 43, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Restyle mode uploads both a reference and input image to the environment-derived bridge URL, doubling the amount of potentially sensitive user media exposed. This is a real trust-boundary issue because the destination is configurable outside the script and not constrained to the advertised LAN use case.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 889)May include surrounding context.

python
"style_weight": str(args.style_weight),
                    "strength": str(args.strength),
                }
                r = httpx.post(
                    f"{BRIDGE_URL}/restyle",
                    files=files,
                    data=data,

Tainted flow: 'BRIDGE_URL' from os.environ.get (line 43, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
91% confidence
Finding

Targeted faceswap sends source and target images, plus face selection metadata, to an unvalidated bridge URL. Given the biometric and personal nature of the data, environment-based redirection can have serious privacy and misuse consequences.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 946)May include surrounding context.

python
"codeformer_weight": str(args.codeformer_weight),
                    "restore_visibility": str(args.restore_visibility),
                }
                r = httpx.post(
                    f"{BRIDGE_URL}/faceswap/targeted",
                    files=files,
                    data=data,

Tainted flow: 'req' from os.environ.get (line 67, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/queue_processor.py (reported line 68)May include surrounding context.

python
try:
        import urllib.request
        req = urllib.request.Request(f"{BRIDGE_URL}/health")
        resp = urllib.request.urlopen(req, timeout=5)
        data = json.loads(resp.read())
        return data.get("status") == "ok" and data.get("comfyui") == "reachable"
    except Exception:

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The manifest presents the skill as a LAN/self-hosted image tool, but the documentation reveals additional behavior: persistent offline queuing, background processing, and automatic delivery via iMessage. This is a material expansion of functionality into messaging and durable data handling, which can surprise users and operators, enable unintended exfiltration of generated or source images, and bypass expectations about when and where content is transmitted.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 164)May include surrounding context.

python
import httpx as _httpx
    if isinstance(e, _httpx.TimeoutException):
        print(f"Error: {operation} timed out. ComfyUI may be overloaded or processing a large job.", file=sys.stderr)
        print(f"Check queue: curl {BRIDGE_URL}/diagnostics | python -m json.tool", file=sys.stderr)
    elif isinstance(e, _httpx.HTTPStatusError):
        status = e.response.status_code
        try:

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code invokes an iMessage CLI and deliberately sets HOME so it can access the user's Messages database/context when run as a LaunchAgent. That grants the skill messaging capability unrelated to the core LAN bridge description, increasing the blast radius to privacy loss, unauthorized message sending, and covert exfiltration of generated content.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/queue_processor.py (reported line 102)May include surrounding context.

python
return False
        # Pass HOME explicitly so imsg finds ~/Library/Messages/chat.db
        # even when running as a LaunchAgent with restricted environment
        send_env = {**os.environ, "HOME": str(Path.home())}
        r = subprocess.run(cmd, capture_output=True, text=True, timeout=30, env=send_env)
        if r.returncode == 0:
            log(f"Delivered to chat {chat_id}")

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

Using shell=True with queue-influenced parameters creates a clear tool-parameter abuse path. Because queued request fields can control command construction and one field is concatenated without safe quoting, an attacker able to inject a queue item could execute arbitrary shell commands under the user's account.

Content

Scanner excerpt · scripts/queue_processor.py (reported line 114)May include surrounding context.

python
shell_cmd += " --text " + subprocess.list2cmdline([text])
        if image_path and Path(image_path).exists():
            shell_cmd += " --file " + subprocess.list2cmdline([str(image_path)])
        r2 = subprocess.run(shell_cmd, shell=True, capture_output=True, text=True, timeout=30, env=send_env)
        if r2.returncode == 0:
            log(f"Delivered to chat {chat_id} (shell fallback)")
            return True

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/queue_processor.py (reported line 205)May include surrounding context.

python
cmd.extend(["-f", output_file])

    # Ensure uv and homebrew binaries are in PATH (launchd has minimal PATH)
    proc_env = {**os.environ, "COMFYUI_BRIDGE_URL": BRIDGE_URL}
    extra_path = str(Path.home() / ".local" / "bin") + ":/opt/homebrew/bin:/usr/local/bin"
    proc_env["PATH"] = extra_path + ":" + proc_env.get("PATH", "/usr/bin:/bin")

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documentation describes capabilities that require shell execution, network access, environment-variable use, and local file reads/writes, but it does not declare any explicit tool scope or permission boundaries. This creates an overbroad, implicit trust model where the agent may invoke sensitive capabilities without transparent user/admin review, increasing the risk of misuse or prompt-triggered abuse.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill supports faceswap and automatic delivery behaviors without prominent consent, privacy, or outbound-sharing warnings. Because faceswap involves biometric/identity-sensitive imagery and the queue can transmit outputs automatically, users may unknowingly process or distribute manipulated personal images without adequate notice or consent controls.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill claims LAN-only, self-hosted image operations, yet its offline queue automatically delivers results later via iMessage. That contradicts the stated trust boundary and can expose user images or transformed content to a different channel than expected, especially if users assume processing remains strictly local and manually controlled.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The routing guide uses broad natural-language triggers such as 'generate an image of' or 'make this look like,' without clear activation boundaries or disambiguation rules. In an agent environment, this can cause over-triggering of powerful file/network/shell-backed actions, potentially processing images, modifying files, or contacting the bridge when the user did not intend to invoke this skill.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/comfyui_generate.py (reported line 53)May include surrounding context.

python
if image_path.suffix.lower() in (".heic", ".heif"):
        jpg_path = image_path.with_suffix(".jpg")
        try:
            result = _sp.run(
                ["sips", "-s", "format", "jpeg", str(image_path), "--out", str(jpg_path)],
                capture_output=True, timeout=15
            )

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script sends generated faceswap outputs to a separate Ollama vision service for QA, which is an additional data sink beyond the documented ComfyUI bridge function. Even though it is hardcoded to localhost, this expands the trust boundary and can expose sensitive face imagery to another local service without clear consent or necessity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The QA check transmits image data to a separate local HTTP service without a clear user warning. In a self-hosted image-processing skill, undisclosed forwarding of face images to another process or model is a meaningful privacy concern even if it stays on localhost.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.