openclaw - ✅(Solved) Fix [Bug]: Comfy plugin: allowPrivateNetwork: true in local mode does not bypass SSRF guard when baseUrl is a DNS hostname resolving to a private IP [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#77922Fetched 2026-05-06 06:19:23
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
2
Author
Timeline (top)
labeled ×2commented ×1cross-referenced ×1referenced ×1

When using the Comfy plugin in mode: "local" with a DNS hostname as baseUrl that resolves to a private/LAN IP (e.g. https://comfy.local.example.com → 192.168.178.xx), the image_generate call is blocked by the SSRF guard with:

Blocked: resolves to private/internal/special-use IP address

Using the same ComfyUI endpoint with an IP literal as baseUrl (e.g. http://192.168.178.xxx:port) works correctly.

Configuration

{ "plugins": { "entries": { "comfy": { "config": { "mode": "local", "baseUrl": "https://comfy.local.example.com", "allowPrivateNetwork": true, "image": { "workflowPath": "~/.openclaw/workflows/comfy/flux-api.json", "promptNodeId": "27", "promptInputName": "text", "outputNodeId": "9" } } } } } }

Root Cause

In workflow-runtime-*.js, resolveComfyNetworkPolicy builds the SSRF bypass policy only when isPrivateOrLoopbackHost(hostname) returns true:

function resolveComfyNetworkPolicy(params) { const hostname = normalizeOptionalLowercaseString(parsed.hostname) ?? ""; if (!hostname || !params.allowPrivateNetwork || !isPrivateOrLoopbackHost(hostname)) return {}; return { apiPolicy: mergeSsrFPolicies( buildHostnameAllowlistPolicyFromSuffixAllowlist([hostname]), ssrfPolicyFromDangerouslyAllowPrivateNetwork(true) ) }; }

isPrivateOrLoopbackHost (in net-*.js) checks if the hostname string is a parseable IP literal or localhost. DNS hostnames like comfy.local.example.com are not parseable as IPs, so it returns false — even though the hostname resolves to 192.168.178.xx (RFC1918 private).

As a result, resolveComfyNetworkPolicy returns {} (no bypass policy). The subsequent HTTP fetch goes through the default SSRF guard, which does resolve DNS and correctly identifies the IP as private → blocked.

The gap: the plugin correctly sets allowPrivateNetwork: true for local mode, but the function that builds the SSRF bypass only works for IP literal hostnames, not DNS hostnames that resolve to private IPs.

Expected Behavior

When mode: "local" and allowPrivateNetwork: true, Comfy API requests to baseUrl should be allowed regardless of whether the hostname is an IP literal or a DNS name resolving to a private IP.

Workaround

Use an IP literal as baseUrl instead of a DNS hostname. This works but loses TLS/SNI and requires knowing the IP address at config time.

Environment

• OpenClaw: latest (installed via npm) • Host: Linux, kernel 6.8.0-110-generic • DNS: Local AdGuard Home resolving *.local.example.com to LAN IPs • ComfyUI: v0.20.1 on Docker

Error Message

Requests to baseUrl values that are DNS hostnames resolving to private/LAN IPs are blocked by the SSRF guard with error: Blocked: resolves to private/internal/special-use IP address. The root cause is that isPrivateOrLoopbackHost() in resolveComfyNetworkPolicy only recognizes IP literals (e.g. 192.168.178.xx) and localhost — not DNS hostnames (e.g. comfy.local.example.com) that resolve to private IPs. Since the function returns false for DNS hostnames, the network bypass policy is never built, and the lower-level SSRF guard (which does resolve DNS) blocks the request.

Root Cause

Root Cause

Fix Action

Fix / Workaround

Workaround

PR fix notes

PR #77944: fix(comfy): bypass SSRF guard for DNS hostnames when allowPrivateNetwork is set in local mode

Description (problem / solution / changelog)

Problem

Closes #77922.

When using the Comfy plugin with mode: "local" (or allowPrivateNetwork: true) and a DNS hostname as baseUrl (e.g. https://comfy.local.example.com) that resolves to a private IP, the SSRF guard blocks the request:

Blocked: resolves to private/internal/special-use IP address

Root cause

resolveComfyNetworkPolicy only applied the private-network SSRF bypass when isPrivateOrLoopbackHost(hostname) returned true. That check matches numeric private IPs and loopback addresses (127.x, 192.168.x, 10.x, fc00::) — but it returns false for DNS names, so the bypass was never applied for DNS-named local endpoints.

Fix

Remove the isPrivateOrLoopbackHost gate in resolveComfyNetworkPolicy:

// Before
if (!hostname || !params.allowPrivateNetwork || !isPrivateOrLoopbackHost(hostname)) {
  return {};
}

// After
if (!hostname || !params.allowPrivateNetwork) {
  return {};
}

When allowPrivateNetwork is set, the configured hostname is always explicitly allowlisted (buildHostnameAllowlistPolicyFromSuffixAllowlist) and private-network IPs are allowed via ssrfPolicyFromDangerouslyAllowPrivateNetwork(true). This is not a blanket bypass — the hostname must match the configured baseUrl.

Also removed the now-unused isPrivateOrLoopbackHost import.

Tests

Added a test in image-generation-provider.test.ts: local mode with a DNS hostname passes a non-null policy to fetchWithSsrFGuard. All 21 comfy tests pass.

Scope

  • extensions/comfy/workflow-runtime.ts — 3 lines changed (removed gate condition + unused import)
  • extensions/comfy/image-generation-provider.test.ts — 1 new test

🤖 Generated with Claude Code

Changed files

  • extensions/comfy/image-generation-provider.test.ts (modified, +54/-0)
  • extensions/comfy/workflow-runtime.ts (modified, +6/-3)
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

When using the Comfy plugin in mode: "local" with a DNS hostname as baseUrl that resolves to a private/LAN IP (e.g. https://comfy.local.example.com → 192.168.178.xx), the image_generate call is blocked by the SSRF guard with:

Blocked: resolves to private/internal/special-use IP address

Using the same ComfyUI endpoint with an IP literal as baseUrl (e.g. http://192.168.178.xxx:port) works correctly.

Configuration

{ "plugins": { "entries": { "comfy": { "config": { "mode": "local", "baseUrl": "https://comfy.local.example.com", "allowPrivateNetwork": true, "image": { "workflowPath": "~/.openclaw/workflows/comfy/flux-api.json", "promptNodeId": "27", "promptInputName": "text", "outputNodeId": "9" } } } } } }

Root Cause

In workflow-runtime-*.js, resolveComfyNetworkPolicy builds the SSRF bypass policy only when isPrivateOrLoopbackHost(hostname) returns true:

function resolveComfyNetworkPolicy(params) { const hostname = normalizeOptionalLowercaseString(parsed.hostname) ?? ""; if (!hostname || !params.allowPrivateNetwork || !isPrivateOrLoopbackHost(hostname)) return {}; return { apiPolicy: mergeSsrFPolicies( buildHostnameAllowlistPolicyFromSuffixAllowlist([hostname]), ssrfPolicyFromDangerouslyAllowPrivateNetwork(true) ) }; }

isPrivateOrLoopbackHost (in net-*.js) checks if the hostname string is a parseable IP literal or localhost. DNS hostnames like comfy.local.example.com are not parseable as IPs, so it returns false — even though the hostname resolves to 192.168.178.xx (RFC1918 private).

As a result, resolveComfyNetworkPolicy returns {} (no bypass policy). The subsequent HTTP fetch goes through the default SSRF guard, which does resolve DNS and correctly identifies the IP as private → blocked.

The gap: the plugin correctly sets allowPrivateNetwork: true for local mode, but the function that builds the SSRF bypass only works for IP literal hostnames, not DNS hostnames that resolve to private IPs.

Expected Behavior

When mode: "local" and allowPrivateNetwork: true, Comfy API requests to baseUrl should be allowed regardless of whether the hostname is an IP literal or a DNS name resolving to a private IP.

Workaround

Use an IP literal as baseUrl instead of a DNS hostname. This works but loses TLS/SNI and requires knowing the IP address at config time.

Environment

• OpenClaw: latest (installed via npm) • Host: Linux, kernel 6.8.0-110-generic • DNS: Local AdGuard Home resolving *.local.example.com to LAN IPs • ComfyUI: v0.20.1 on Docker

Steps to reproduce

Steps to Reproduce

  1. Set up ComfyUI on a LAN host (e.g. Docker on Ip:Port)

  2. Configure a DNS hostname pointing to a private/LAN IP (e.g. AdGuard Home: comfy.local.example.com → Ip of server hosting Comfy)

  3. Set up a reverse proxy (e.g. AdGuard) to forward https://comfy.local.example.com to the ComfyUI container

  4. Configure OpenClaw Comfy plugin in openclaw.json:{ "plugins": { "entries": { "comfy": { "config": { "mode": "local", "baseUrl": "https://comfy.local.example.com", "allowPrivateNetwork": true, "image": { "workflowPath": "~/.openclaw/workflows/comfy/flux-api.json", "promptNodeId": "6", "outputNodeId": "9" } } } } } }

  5. Restart OpenClaw Gateway

  6. Call image_generate with model: "comfy/workflow" and any prompt

  7. Request fails with: Blocked: resolves to private/internal/special-use IP address

  8. Change baseUrl to http://ip:port (IP literal)

  9. Restart Gateway and retry — request succeeds

Expected behavior

When mode: "local" and allowPrivateNetwork: true, the Comfy plugin should allow requests to the configured baseUrl regardless of whether it's a DNS hostname or IP literal. The allowPrivateNetwork: true flag (automatically set for local mode) should permit private network access, including for DNS hostnames that resolve to private IPs.

Actual behavior

Requests to baseUrl values that are DNS hostnames resolving to private/LAN IPs are blocked by the SSRF guard with error: Blocked: resolves to private/internal/special-use IP address. The root cause is that isPrivateOrLoopbackHost() in resolveComfyNetworkPolicy only recognizes IP literals (e.g. 192.168.178.xx) and localhost — not DNS hostnames (e.g. comfy.local.example.com) that resolve to private IPs. Since the function returns false for DNS hostnames, the network bypass policy is never built, and the lower-level SSRF guard (which does resolve DNS) blocks the request.

OpenClaw version

v2026.5.3-1

Operating system

Ubuntu 24.04.4 LTS

Install method

npm global

Model

gpt 5.5

Provider / routing chain

openclaw local -> codex via api

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

extent analysis

TL;DR

The issue can be fixed by modifying the isPrivateOrLoopbackHost function to also consider DNS hostnames that resolve to private IPs or by using an IP literal as the baseUrl.

Guidance

  • The root cause of the issue is that the isPrivateOrLoopbackHost function only recognizes IP literals and localhost, not DNS hostnames that resolve to private IPs.
  • To fix this, the resolveComfyNetworkPolicy function needs to be modified to handle DNS hostnames that resolve to private IPs.
  • A possible solution is to perform a DNS lookup on the hostname and check if the resolved IP is a private IP.
  • Another workaround is to use an IP literal as the baseUrl instead of a DNS hostname, but this loses TLS/SNI and requires knowing the IP address at config time.

Example

function isPrivateOrLoopbackHost(hostname) {
  const ip = dns.lookup(hostname);
  return ip && (ip.startsWith('192.168.') || ip.startsWith('10.') || ip.startsWith('172.16.') || ip === '127.0.0.1' || ip === '::1');
}

Note: This example is a simplified version and may need to be adapted to the actual implementation.

Notes

  • The provided example is a possible solution, but it may not be the only one and may require additional modifications to work correctly.
  • The issue is specific to the Comfy plugin and the resolveComfyNetworkPolicy function.

Recommendation

Apply workaround: Use an IP literal as the baseUrl instead of a DNS hostname, as this is a simpler solution that does not require modifying the isPrivateOrLoopbackHost function. However, this may not be desirable due to the loss of TLS/SNI and the need to know the IP address at config time.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

When mode: "local" and allowPrivateNetwork: true, the Comfy plugin should allow requests to the configured baseUrl regardless of whether it's a DNS hostname or IP literal. The allowPrivateNetwork: true flag (automatically set for local mode) should permit private network access, including for DNS hostnames that resolve to private IPs.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: Comfy plugin: allowPrivateNetwork: true in local mode does not bypass SSRF guard when baseUrl is a DNS hostname resolving to a private IP [1 pull requests, 1 comments, 2 participants]