openclaw - ✅(Solved) Fix WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY applies dangerouslyAllowPrivateNetwork to all 10 web search providers [1 pull requests, 2 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#74357Fetched 2026-04-30 06:25:01
View on GitHub
Comments
2
Participants
2
Timeline
23
Reactions
2
Timeline (top)
subscribed ×10referenced ×8commented ×2mentioned ×2

src/agents/tools/web-guarded-fetch.ts:10–13 defines a single SSRF policy used by every web search provider in OpenClaw:

```typescript const WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY: SsrFPolicy = { dangerouslyAllowPrivateNetwork: true, allowRfc2544BenchmarkRange: true, }; ```

This policy is applied via withTrustedWebToolsEndpointwithTrustedWebSearchEndpoint / postTrustedWebToolsJson, which is called by all 10 bundled web search providers:

  • extensions/duckduckgo/src/ddg-client.ts
  • extensions/brave/src/brave-web-search-provider.runtime.ts
  • extensions/searxng/src/searxng-client.ts
  • extensions/perplexity/src/perplexity-web-search-provider.runtime.ts
  • extensions/moonshot/src/kimi-web-search-provider.runtime.ts
  • extensions/xai/src/x-search-shared.ts, web-search-shared.ts, code-execution-shared.ts
  • extensions/exa/src/exa-web-search-provider.runtime.ts
  • extensions/google/src/gemini-web-search-provider.runtime.ts
  • extensions/tavily/src/tavily-client.ts
  • extensions/minimax/src/minimax-web-search-provider.runtime.ts

The policy is also re-exported via the plugin SDK at src/plugin-sdk/provider-web-fetch.ts:10, making it available to third-party plugins.

Root Cause

src/agents/tools/web-guarded-fetch.ts:10–13 defines a single SSRF policy used by every web search provider in OpenClaw:

```typescript const WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY: SsrFPolicy = { dangerouslyAllowPrivateNetwork: true, allowRfc2544BenchmarkRange: true, }; ```

This policy is applied via withTrustedWebToolsEndpointwithTrustedWebSearchEndpoint / postTrustedWebToolsJson, which is called by all 10 bundled web search providers:

  • extensions/duckduckgo/src/ddg-client.ts
  • extensions/brave/src/brave-web-search-provider.runtime.ts
  • extensions/searxng/src/searxng-client.ts
  • extensions/perplexity/src/perplexity-web-search-provider.runtime.ts
  • extensions/moonshot/src/kimi-web-search-provider.runtime.ts
  • extensions/xai/src/x-search-shared.ts, web-search-shared.ts, code-execution-shared.ts
  • extensions/exa/src/exa-web-search-provider.runtime.ts
  • extensions/google/src/gemini-web-search-provider.runtime.ts
  • extensions/tavily/src/tavily-client.ts
  • extensions/minimax/src/minimax-web-search-provider.runtime.ts

The policy is also re-exported via the plugin SDK at src/plugin-sdk/provider-web-fetch.ts:10, making it available to third-party plugins.

Fix Action

Fix

Split the policy so dangerouslyAllowPrivateNetwork is only active for providers where the endpoint URL is user-configured as a private address (SearXNG, and any future self-hosted provider). Cloud providers with fixed public API endpoints should use the strict policy.

Option A — per-provider opt-in: ```typescript // web-guarded-fetch.ts const STRICT_WEB_TOOLS_SSRF_POLICY: SsrFPolicy = {}; const SELF_HOSTED_WEB_TOOLS_SSRF_POLICY: SsrFPolicy = { dangerouslyAllowPrivateNetwork: true, };

export async function withTrustedWebToolsEndpoint(...) { /* uses STRICT / } export async function withSelfHostedWebToolsEndpoint(...) { / uses SELF_HOSTED */ } ```

Then SearXNG switches to withSelfHostedWebToolsEndpoint; all other providers stay on withTrustedWebToolsEndpoint with the strict policy.

Option B — URL-based guard: Before making the request in withTrustedWebToolsEndpoint, check whether the URL resolves to a private address and reject it unless the caller has explicitly opted into private network access.

PR fix notes

PR #74360: fix(ssrf): restrict dangerouslyAllowPrivateNetwork to self-hosted providers only

Description (problem / solution / changelog)

Closes #74357

What changed

src/agents/tools/web-guarded-fetch.ts:10–13 previously defined a single SSRF policy applied to every web search call:

// before — applied to ALL 10 web search providers
const WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY: SsrFPolicy = {
  dangerouslyAllowPrivateNetwork: true,
  allowRfc2544BenchmarkRange: true,
};

This is replaced with two policies and two endpoint functions:

// after — cloud providers get the strict default
const WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY: SsrFPolicy = {};

// self-hosted providers (SearXNG) keep private network access
const WEB_TOOLS_SELF_HOSTED_SSRF_POLICY: SsrFPolicy = {
  dangerouslyAllowPrivateNetwork: true,
  allowRfc2544BenchmarkRange: true,
};

export async function withSelfHostedWebToolsEndpoint<T>(...) // new

SearXNG is the only provider switched to withSelfHostedWebSearchEndpoint. All other providers (DuckDuckGo, Brave, Perplexity, xAI, Exa, Gemini, Tavily, Kimi, MiniMax) continue using withTrustedWebSearchEndpoint, which now uses the strict policy.

withSelfHostedWebToolsEndpoint and withSelfHostedWebSearchEndpoint are exported from the plugin SDK so third-party self-hosted provider plugins can opt in explicitly.

Why SearXNG still works

SearXNG already validates its base URL in validateSearxngBaseUrl() before making any request — HTTP URLs must target a private/loopback host via assertHttpUrlTargetsPrivateNetwork. The self-hosted endpoint preserves the private network access that the fetch call needs after that validation passes.

Files changed

  • src/agents/tools/web-guarded-fetch.ts — split policy, add withSelfHostedWebToolsEndpoint
  • src/agents/tools/web-search-provider-common.ts — add withSelfHostedWebSearchEndpoint
  • extensions/searxng/src/searxng-client.ts — switch to withSelfHostedWebSearchEndpoint
  • src/plugin-sdk/provider-web-search.ts — export withSelfHostedWebSearchEndpoint
  • src/plugin-sdk/provider-web-fetch.ts — export withSelfHostedWebToolsEndpoint

Changed files

  • extensions/searxng/src/searxng-client.ts (modified, +2/-2)
  • src/agents/tools/web-guarded-fetch.ssrf.test.ts (added, +138/-0)
  • src/agents/tools/web-guarded-fetch.test.ts (modified, +29/-2)
  • src/agents/tools/web-guarded-fetch.ts (modified, +21/-1)
  • src/agents/tools/web-search-provider-common.ts (modified, +27/-1)
  • src/plugin-sdk/provider-web-fetch.ts (modified, +1/-0)
  • src/plugin-sdk/provider-web-search.ts (modified, +1/-0)
RAW_BUFFERClick to expand / collapse

Summary

src/agents/tools/web-guarded-fetch.ts:10–13 defines a single SSRF policy used by every web search provider in OpenClaw:

```typescript const WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY: SsrFPolicy = { dangerouslyAllowPrivateNetwork: true, allowRfc2544BenchmarkRange: true, }; ```

This policy is applied via withTrustedWebToolsEndpointwithTrustedWebSearchEndpoint / postTrustedWebToolsJson, which is called by all 10 bundled web search providers:

  • extensions/duckduckgo/src/ddg-client.ts
  • extensions/brave/src/brave-web-search-provider.runtime.ts
  • extensions/searxng/src/searxng-client.ts
  • extensions/perplexity/src/perplexity-web-search-provider.runtime.ts
  • extensions/moonshot/src/kimi-web-search-provider.runtime.ts
  • extensions/xai/src/x-search-shared.ts, web-search-shared.ts, code-execution-shared.ts
  • extensions/exa/src/exa-web-search-provider.runtime.ts
  • extensions/google/src/gemini-web-search-provider.runtime.ts
  • extensions/tavily/src/tavily-client.ts
  • extensions/minimax/src/minimax-web-search-provider.runtime.ts

The policy is also re-exported via the plugin SDK at src/plugin-sdk/provider-web-fetch.ts:10, making it available to third-party plugins.

Why dangerouslyAllowPrivateNetwork exists

SearXNG is a self-hosted search engine — users configure it at a private IP like http://192.168.1.10:8080. That is the only provider where private network access is intentional and expected.

Impact

Every web search call made by DuckDuckGo, Brave, Perplexity, xAI, Exa, Gemini, Tavily, Moonshot, and MiniMax can follow HTTP redirects or reach private RFC-1918 addresses (10.x.x.x, 172.16–31.x.x, 192.168.x.x). In a cloud or Docker deployment this includes:

  • Internal metadata endpoints (e.g. http://169.254.169.254/ on AWS/GCP/Azure — link-local, not RFC-1918, but relevant in practice)
  • Other containers on the same Docker network
  • Internal APIs, admin panels, and databases not intended to be reachable from the agent

The trigger does not require a code change — a malicious web search result that returns a redirect to an internal URL, or a user instruction to fetch a specific URL, is sufficient.

Fix

Split the policy so dangerouslyAllowPrivateNetwork is only active for providers where the endpoint URL is user-configured as a private address (SearXNG, and any future self-hosted provider). Cloud providers with fixed public API endpoints should use the strict policy.

Option A — per-provider opt-in: ```typescript // web-guarded-fetch.ts const STRICT_WEB_TOOLS_SSRF_POLICY: SsrFPolicy = {}; const SELF_HOSTED_WEB_TOOLS_SSRF_POLICY: SsrFPolicy = { dangerouslyAllowPrivateNetwork: true, };

export async function withTrustedWebToolsEndpoint(...) { /* uses STRICT / } export async function withSelfHostedWebToolsEndpoint(...) { / uses SELF_HOSTED */ } ```

Then SearXNG switches to withSelfHostedWebToolsEndpoint; all other providers stay on withTrustedWebToolsEndpoint with the strict policy.

Option B — URL-based guard: Before making the request in withTrustedWebToolsEndpoint, check whether the URL resolves to a private address and reject it unless the caller has explicitly opted into private network access.

Affected files

  • src/agents/tools/web-guarded-fetch.ts:10–13 — policy definition
  • src/agents/tools/web-search-provider-common.ts:85–86, 108–109 — shared call sites
  • src/plugin-sdk/provider-web-fetch.ts:10–11 — SDK re-export
  • All 10 extension files listed above

extent analysis

TL;DR

Split the SSRF policy to restrict dangerouslyAllowPrivateNetwork to only self-hosted providers like SearXNG.

Guidance

  • Identify self-hosted providers that require private network access and create a separate policy for them.
  • Update withTrustedWebToolsEndpoint to use a strict policy for cloud providers with fixed public API endpoints.
  • Consider implementing a URL-based guard to reject private address requests unless the caller has opted-in.
  • Review and update the 10 affected extension files to use the new policy or endpoint.

Example

const STRICT_WEB_TOOLS_SSRF_POLICY: SsrFPolicy = {};
const SELF_HOSTED_WEB_TOOLS_SSRF_POLICY: SsrFPolicy = {
  dangerouslyAllowPrivateNetwork: true,
};

Notes

The fix requires updating multiple files and considering the implications of private network access for each provider. The URL-based guard approach may add complexity but provides an additional layer of security.

Recommendation

Apply workaround by implementing Option A — per-provider opt-in to restrict private network access to only self-hosted providers, as it provides a clear and maintainable solution.

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