openclaw - 💡(How to fix) Fix feat(llm-provider): expose allowPrivateNetwork for internal-network LLM gateways

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…

After upgrading to 2026.5.12, LLM provider calls to internal-network gateways (e.g. Docker compose sibling containers) get blocked by the new SSRF guard with SsrFBlockedError: resolves to private/internal/special-use IP address, and there is no config field or env var to opt in for a specific provider.

Error Message

[provider-transport-fetch] [model-fetch] error provider=openai api=openai-completions model=hermes-agent name=SsrFBlockedError [agent/embedded] embedded run agent end: isError=true error=LLM request failed: network connection error

Root Cause

Plus update `models.providers.openai.baseUrl` to match. Works because Node undici uses normal DNS resolution and doesn't enforce RFC 6761 `.localhost` -> 127.0.0.1 mapping the way some curl builds do.

Fix Action

Fix / Workaround

Current workaround (verified working)

Code Example

[security] blocked URL fetch (url-fetch) targetOrigin=http://hermes:8642 reason=Blocked: resolves to private/internal/special-use IP address
   [provider-transport-fetch] [model-fetch] error provider=openai api=openai-completions model=hermes-agent name=SsrFBlockedError
   [agent/embedded] embedded run agent end: isError=true error=LLM request failed: network connection error
RAW_BUFFERClick to expand / collapse

Summary

After upgrading to 2026.5.12, LLM provider calls to internal-network gateways (e.g. Docker compose sibling containers) get blocked by the new SSRF guard with SsrFBlockedError: resolves to private/internal/special-use IP address, and there is no config field or env var to opt in for a specific provider.

Environment

  • OpenClaw 2026.5.12 (image ghcr.io/openclaw/openclaw:2026.5.12, arm64, Node 24.14.0)
  • Docker compose, OpenClaw + LLM gateway (Hermes) as sibling services on a bridge network
  • baseUrl: http://hermes:8642/v1 (internal hostname, resolves to 172.18.0.x)

Repro

  1. Run OpenClaw 2026.5.12 in compose with models.providers.openai.baseUrl pointing to another container by service name (e.g. http://hermes:8642/v1)
  2. Trigger any LLM call (e.g. send a message via Telegram channel)
  3. Observe in OpenClaw stdout:
    [security] blocked URL fetch (url-fetch) targetOrigin=http://hermes:8642 reason=Blocked: resolves to private/internal/special-use IP address
    [provider-transport-fetch] [model-fetch] error provider=openai api=openai-completions model=hermes-agent name=SsrFBlockedError
    [agent/embedded] embedded run agent end: isError=true error=LLM request failed: network connection error
  4. Result: bot replies with `Something went wrong while processing your request`

Why config-level opt-in is needed

  • `models.providers.<name>` schema rejects `allowPrivateNetwork`, `dangerouslyAllowPrivateNetwork`, `network.dangerouslyAllowPrivateNetwork` — all three return `Config validation failed: Unrecognized key`
  • No matching env var exists (greps under `OPENCLAW_ALLOW`/`PRIVATE`/`NETWORK` return only `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS` which is WS-specific)
  • `shouldAutoAllowLoopbackModelRequest()` only auto-allows hostnames matching `localhost`, `*.localhost`, or loopback IP literals — not Docker service hostnames
  • Channel plugins (e.g. Tlon, Matrix) already expose `dangerouslyAllowPrivateNetwork` in their config schema, but LLM provider schema does not

Current workaround (verified working)

Add a `.localhost`-suffixed network alias to the gateway service in `docker-compose.yml`, then use it in `baseUrl`. `isLoopbackProviderBaseUrl` checks only the hostname suffix, so the loopback policy auto-applies regardless of the resolved IP:

```yaml hermes: networks: triad-net: aliases: - hermes.localhost # SSRF bypass via .localhost suffix openclaw: environment: OPENCLAW_LLM_BASE_URL: http://hermes.localhost:8642/v1 ```

Plus update `models.providers.openai.baseUrl` to match. Works because Node undici uses normal DNS resolution and doesn't enforce RFC 6761 `.localhost` -> 127.0.0.1 mapping the way some curl builds do.

This works but is a hostname-spoofing trick rather than an intended escape hatch.

Proposed fix

Add an optional field to `models.providers.<name>` schema:

```ts allowPrivateNetwork?: boolean // or dangerouslyAllowPrivateNetwork ```

Plumb it through `provider-request-config.ts` so it overrides the SSRF check for that provider only (per-provider scope, doesn't relax the global policy).

Related

  • #56061 (long-poll dead-socket fix, shipped 2026.3.22)
  • #81746 (telegram isolated worker fix #81132, shipped 2026.5.12)
  • #61570 (telegram startup hang root cause cluster)

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…

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 - 💡(How to fix) Fix feat(llm-provider): expose allowPrivateNetwork for internal-network LLM gateways