openclaw - 💡(How to fix) Fix web_fetch fails with "resolves to private/internal/special-use IP address" in proxy environments using fake-ip mode [1 participants]

Official PRs (…)
ON THIS PAGE

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#60859Fetched 2026-04-08 02:46:22
View on GitHub
Comments
0
Participants
1
Timeline
18
Reactions
0
Author
Participants
Timeline (top)
referenced ×17cross-referenced ×1

web_fetch fails for all URLs when running behind a transparent proxy (Surge, Clash, etc.) with fake-ip mode enabled. The proxy's DNS hijacking returns addresses in the 198.18.0.0/15 range (RFC 2544 Benchmark Testing), which triggers OpenClaw's SSRF protection.

Error Message

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

Error Message Enhancement

When web_fetch is blocked by RFC 2544 range detection, include a hint in the error message:

Root Cause

The SSRF protection layer in fetchWithSsrFGuard resolves DNS locally and checks the resulting IP against blocked ranges. In fake-ip proxy environments, DNS queries return synthetic addresses (typically 198.18.x.x) that the proxy intercepts and forwards to the real destination. The local DNS result does not represent the actual connection target.

Call chain:

web_fetch → runWebFetch()
  → fetchWithWebToolsNetworkGuard() (strict mode, no policy)
    → fetchWithSsrFGuard(withStrictGuardedFetchMode(...))
      → resolvePinnedHostnameWithPolicy(hostname, { policy: undefined })
        → DNS lookup → 198.18.x.x (fake-ip from proxy)
        → assertAllowedResolvedAddressesOrThrow()
          → isBlockedSpecialUseIpv4Address(ip, { allowRfc2544BenchmarkRange: false })
          → BLOCKED ❌

Note: The codebase already has an allowRfc2544BenchmarkRange flag and uses it for trusted internal endpoints (Firecrawl API, Discord media), but the web_fetch strict mode path does not pass it through.

Fix Action

Fix / Workaround

ConditionSSRF Strategy
assumeProxyEnvironment: true OR HTTP_PROXY/HTTPS_PROXY env detectedHostname blocklist only (skip DNS IP check)
NeitherCurrent strict mode unchanged (DNS resolve + IP check + pinned dispatcher)

Code Example

web_fetch → runWebFetch()
fetchWithWebToolsNetworkGuard() (strict mode, no policy)
fetchWithSsrFGuard(withStrictGuardedFetchMode(...))
resolvePinnedHostnameWithPolicy(hostname, { policy: undefined })
DNS lookup → 198.18.x.x (fake-ip from proxy)
assertAllowedResolvedAddressesOrThrow()
isBlockedSpecialUseIpv4Address(ip, { allowRfc2544BenchmarkRange: false })
BLOCKED
---

network:
  assumeProxyEnvironment: true  # default: false

---

Blocked: resolves to private/internal/special-use IP address.
Hint: If you use a proxy with fake-ip mode (Surge, Clash, etc.), set `network.assumeProxyEnvironment: true` in your OpenClaw config.
RAW_BUFFERClick to expand / collapse

Issue Draft: web_fetch blocked by SSRF protection in proxy/fake-ip environments


Title: web_fetch fails with "resolves to private/internal/special-use IP address" in proxy environments using fake-ip mode

Description

web_fetch fails for all URLs when running behind a transparent proxy (Surge, Clash, etc.) with fake-ip mode enabled. The proxy's DNS hijacking returns addresses in the 198.18.0.0/15 range (RFC 2544 Benchmark Testing), which triggers OpenClaw's SSRF protection.

Steps to Reproduce

  1. Run OpenClaw on a machine with Surge/Clash in fake-ip (enhanced) mode
  2. Use web_fetch to fetch any public URL (e.g., https://example.com)
  3. Error: Blocked: resolves to private/internal/special-use IP address

Root Cause

The SSRF protection layer in fetchWithSsrFGuard resolves DNS locally and checks the resulting IP against blocked ranges. In fake-ip proxy environments, DNS queries return synthetic addresses (typically 198.18.x.x) that the proxy intercepts and forwards to the real destination. The local DNS result does not represent the actual connection target.

Call chain:

web_fetch → runWebFetch()
  → fetchWithWebToolsNetworkGuard() (strict mode, no policy)
    → fetchWithSsrFGuard(withStrictGuardedFetchMode(...))
      → resolvePinnedHostnameWithPolicy(hostname, { policy: undefined })
        → DNS lookup → 198.18.x.x (fake-ip from proxy)
        → assertAllowedResolvedAddressesOrThrow()
          → isBlockedSpecialUseIpv4Address(ip, { allowRfc2544BenchmarkRange: false })
          → BLOCKED ❌

Note: The codebase already has an allowRfc2544BenchmarkRange flag and uses it for trusted internal endpoints (Firecrawl API, Discord media), but the web_fetch strict mode path does not pass it through.

Proposed Solution

Add a user-facing configuration option to declare a proxy environment. When enabled, web_fetch skips DNS-based IP checks (which are meaningless behind a proxy) and relies on hostname-level blocklist only.

Configuration

network:
  assumeProxyEnvironment: true  # default: false

Behavior

ConditionSSRF Strategy
assumeProxyEnvironment: true OR HTTP_PROXY/HTTPS_PROXY env detectedHostname blocklist only (skip DNS IP check)
NeitherCurrent strict mode unchanged (DNS resolve + IP check + pinned dispatcher)

What changes

  • When proxy environment is detected/configured, fetchWithWebToolsNetworkGuard still resolves DNS (needed for connection establishment in transparent proxy scenarios), but skips the IP range checks in assertAllowedResolvedAddressesOrThrow
  • Hostname blocklist (localhost, .internal, .local, metadata.google.internal) always remains active regardless of proxy mode
  • Requests use EnvHttpProxyAgent when HTTP_PROXY/HTTPS_PROXY is set, or standard fetch otherwise (transparent proxy handles routing at network level)
  • No changes to behavior when proxy is not detected/configured

Security Analysis

Attack VectorProxy ModeNon-Proxy Mode
SSRF to localhost✅ Blocked by hostname blocklist✅ Blocked by hostname + IP check
SSRF to internal IPsDelegated to proxy routing rules✅ Blocked by IP check
DNS rebindingDelegated to proxy✅ Blocked by pinned DNS

In proxy environments, the proxy itself controls routing and DNS resolution. OpenClaw cannot and should not attempt to enforce IP-level SSRF checks on synthetic DNS results that don't correspond to actual connection targets. The hostname blocklist provides sufficient protection against obvious SSRF vectors.

Error Message Enhancement

When web_fetch is blocked by RFC 2544 range detection, include a hint in the error message:

Blocked: resolves to private/internal/special-use IP address.
Hint: If you use a proxy with fake-ip mode (Surge, Clash, etc.), set `network.assumeProxyEnvironment: true` in your OpenClaw config.

Environment

  • OpenClaw: 2026.3.28
  • Proxy: Surge (Enhanced Mode / fake-ip)
  • DNS returns: 198.18.x.x for all domains
  • curl works fine (traffic routed through proxy)
  • web_search works fine (server-side via Gemini API, no local DNS involved)

extent analysis

TL;DR

To fix the web_fetch issue behind a transparent proxy with fake-ip mode, enable the assumeProxyEnvironment configuration option to skip DNS-based IP checks.

Guidance

  • Set network.assumeProxyEnvironment: true in your OpenClaw config to declare a proxy environment and rely on hostname-level blocklist only.
  • Verify that the proxy environment is correctly detected by checking the HTTP_PROXY/HTTPS_PROXY environment variables.
  • Test web_fetch with the new configuration to ensure it can fetch public URLs without being blocked by SSRF protection.
  • Be aware that this change delegates SSRF protection to the proxy's routing rules in proxy environments.

Example

network:
  assumeProxyEnvironment: true

This configuration change allows web_fetch to work behind a transparent proxy with fake-ip mode by skipping DNS-based IP checks.

Notes

This solution assumes that the proxy environment is correctly configured and functioning as expected. The assumeProxyEnvironment option should only be enabled when running behind a trusted proxy.

Recommendation

Apply the workaround by setting network.assumeProxyEnvironment: true in your OpenClaw config, as this allows web_fetch to function correctly behind a transparent proxy with fake-ip mode while maintaining sufficient SSRF protection through the hostname blocklist.

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