openclaw - ✅(Solved) Fix web_fetch SSRF guard incompatible with Clash TUN fake-ip mode [1 pull requests, 1 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#59395Fetched 2026-04-08 02:24:19
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
0
Participants
Timeline (top)
referenced ×3cross-referenced ×2

Root Cause

Clash's fake-ip mode returns placeholder IPs from the 198.18.0.0/15 range (IANA reserved for benchmarking) for all DNS queries. The actual routing happens at the TUN network layer — the fake IP is just a token that the virtual NIC intercepts and forwards to the real destination.

However, web_fetch performs an application-layer DNS pre-check before initiating any HTTP request:

web_fetch(url)
  → DNS resolve → gets 198.18.0.x (fake IP)
  → SSRF check  → blocked: special-use IP ❌
  → (never reaches the actual HTTP request)

The SSRF guard fires before any proxy (HTTP_PROXY / HTTPS_PROXY) can intervene, because the guard runs at the DNS resolution stage, not the connection stage.

Fix Action

Workaround

Switching Clash DNS mode from fake-ip to redir-host resolves the issue — DNS returns real IPs, SSRF check passes. However, this reduces DNS privacy (DNS queries are sent to upstream resolvers rather than being handled locally).

PR fix notes

PR #59443: fix(fetch-guard): skip DNS pre-flight in trusted-env-proxy mode when proxy is configured

Description (problem / solution / changelog)

Problem

In environments where the system DNS resolver returns non-routable placeholder addresses — most notably Clash TUN fake-ip mode (which returns 198.18.x.x for every hostname) — web_fetch fails with an SSRF block even when a valid HTTP proxy is configured.

Root cause: fetchWithSsrFGuard always called resolvePinnedHostnameWithPolicy (local DNS pre-flight) before checking whether a trusted env proxy was configured. In fake-ip mode the resolver returns 198.18.0.x (IANA special-use range), which the SSRF guard correctly rejects — but the proxy never gets a chance to resolve the real address.

Execution order before this fix:

  1. DNS pre-flight → gets fake 198.18.0.xSSRF block ❌
  2. (never reached) Check for HTTPS_PROXY → create EnvHttpProxyAgent

Fix

Reorder the check in fetchWithSsrFGuard: if TRUSTED_ENV_PROXY mode is active and a proxy env var is set, create the EnvHttpProxyAgent dispatcher immediately and skip local DNS pinning entirely. DNS resolution is delegated to the proxy, which is the correct behaviour for an operator-controlled proxy.

When no proxy is configured, the existing resolvePinnedHostnameWithPolicy path is preserved in full.

Security

  • STRICT mode: unchanged — DNS pre-flight + SSRF guard always runs.
  • TRUSTED_ENV_PROXY + no proxy configured: unchanged — falls through to the existing SSRF path.
  • TRUSTED_ENV_PROXY + proxy configured: DNS delegated to proxy (same semantics as before for the canUseTrustedEnvProxy branch, just moved earlier to avoid the spurious pre-flight failure).

Tests

Added two new test cases in fetch-guard.ssrf.test.ts:

  1. fake-ip compatibility — verifies that the local lookupFn is never called in trusted proxy mode and that EnvHttpProxyAgent is used as the dispatcher.
  2. no proxy configured — verifies that private IP literals are still blocked even in TRUSTED_ENV_PROXY mode when no proxy env var is set.

All 21 tests pass.

Closes #59395

Changed files

  • src/infra/net/fetch-guard.ssrf.test.ts (modified, +57/-0)
  • src/infra/net/fetch-guard.ts (modified, +20/-8)

Code Example

web_fetch(url)
DNS resolve → gets 198.18.0.x (fake IP)
SSRF check  → blocked: special-use IP   (never reaches the actual HTTP request)

---

# All domains resolve to fake IPs under Clash TUN fake-ip mode
dig google.com +short   # → 198.18.0.21
dig github.com +short   # → 198.18.0.70
dig example.com +short  # → 198.18.0.22

---

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

Problem

When running OpenClaw with Clash (or any TUN-based proxy) in fake-ip mode, web_fetch is completely broken for all domains.

Root Cause

Clash's fake-ip mode returns placeholder IPs from the 198.18.0.0/15 range (IANA reserved for benchmarking) for all DNS queries. The actual routing happens at the TUN network layer — the fake IP is just a token that the virtual NIC intercepts and forwards to the real destination.

However, web_fetch performs an application-layer DNS pre-check before initiating any HTTP request:

web_fetch(url)
  → DNS resolve → gets 198.18.0.x (fake IP)
  → SSRF check  → blocked: special-use IP ❌
  → (never reaches the actual HTTP request)

The SSRF guard fires before any proxy (HTTP_PROXY / HTTPS_PROXY) can intervene, because the guard runs at the DNS resolution stage, not the connection stage.

Environment

  • macOS (Apple Silicon) + Clash Verge (mihomo core), fake-ip mode
  • Windows + Clash Verge, fake-ip mode (reproduced on both)
  • HTTPS_PROXY=http://127.0.0.1:7897 set in LaunchAgent EnvironmentVariables — does not help because the SSRF pre-check happens before the proxy dispatcher is invoked

Verification

# All domains resolve to fake IPs under Clash TUN fake-ip mode
dig google.com +short   # → 198.18.0.21
dig github.com +short   # → 198.18.0.70
dig example.com +short  # → 198.18.0.22

Every web_fetch call fails with:

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

Workaround

Switching Clash DNS mode from fake-ip to redir-host resolves the issue — DNS returns real IPs, SSRF check passes. However, this reduces DNS privacy (DNS queries are sent to upstream resolvers rather than being handled locally).

Proposed Fix

Consider one or more of the following:

  1. Config option to skip DNS pre-check when a proxy is configured — if HTTPS_PROXY is set, the application won't do its own DNS resolution anyway, so the pre-check is redundant and should be skippable.

  2. Configurable SSRF allowlist for IP ranges — allow users to whitelist specific IP ranges (e.g. 198.18.0.0/15) that are known to be local proxy tokens, not real destinations.

  3. Detect fake-ip pattern — if the resolved IP falls in 198.18.0.0/15 AND a proxy is configured, trust the proxy to handle routing rather than blocking.

Impact

Clash TUN fake-ip is the default and recommended mode in Clash Verge and many other Clash-based clients. This makes web_fetch effectively unusable for a large portion of users running OpenClaw on macOS/Windows with a TUN proxy — which is an extremely common setup in regions where proxy usage is prevalent.

browser tool works fine (operates at network layer), web_search works fine (cloud-side), but web_fetch is the only tool broken by this architectural conflict.

extent analysis

TL;DR

To fix the web_fetch issue with Clash's fake-ip mode, consider adding a config option to skip DNS pre-check when a proxy is configured or implement a configurable SSRF allowlist for IP ranges.

Guidance

  • Identify if the issue is specific to the web_fetch tool and if other tools like browser and web_search are working as expected.
  • Verify that the problem is caused by the SSRF pre-check blocking the fake IP addresses returned by Clash's fake-ip mode.
  • Consider switching to redir-host DNS mode in Clash as a temporary workaround, but be aware that this reduces DNS privacy.
  • Evaluate the proposed fixes, such as adding a config option to skip DNS pre-check or implementing a configurable SSRF allowlist, to determine the best solution for your use case.

Example

No code snippet is provided as the issue is more related to configuration and architectural changes.

Notes

The issue seems to be specific to the combination of OpenClaw, Clash, and fake-ip mode, and the proposed fixes are targeted at addressing this specific conflict. The solution may not be applicable to other setups or configurations.

Recommendation

Apply a workaround by switching to redir-host DNS mode in Clash, as this is a known solution that resolves the issue, although it reduces DNS privacy. A more permanent solution would involve implementing one of the proposed fixes, such as adding a config option to skip DNS pre-check or implementing a configurable SSRF allowlist.

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