From 087d122e38fed3c9cada06e64cc8fa36c4a30adc Mon Sep 17 00:00:00 2001 From: sunkinux Date: Mon, 2 Mar 2026 10:21:33 +0800 Subject: [PATCH 1/5] fix: allow RFC 2544 benchmark range in trusted SSRF policy Add allowRfc2544BenchmarkRange: true to WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY to fix web_fetch being blocked when using Clash fake-ip mode (198.18.0.0/15). This only affects withTrustedWebToolsEndpoint, keeping strict SSRF behavior for withStrictWebToolsEndpoint (citation redirect resolution). --- src/agents/tools/web-guarded-fetch.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/agents/tools/web-guarded-fetch.ts b/src/agents/tools/web-guarded-fetch.ts index 2f905a215c0..f427eabcab3 100644 --- a/src/agents/tools/web-guarded-fetch.ts +++ b/src/agents/tools/web-guarded-fetch.ts @@ -7,6 +7,7 @@ import type { SsrFPolicy } from "../../infra/net/ssrf.js"; const WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY: SsrFPolicy = { dangerouslyAllowPrivateNetwork: true, + allowRfc2544BenchmarkRange: true, }; type WebToolGuardedFetchOptions = Omit & { From 3832393555b569a85acb2d5176adc89f22a57288 Mon Sep 17 00:00:00 2001 From: sunkinux Date: Mon, 9 Mar 2026 21:31:07 +0800 Subject: [PATCH 2/5] fix(web-fetch): allow RFC 2544 benchmark range for fake-ip proxy compatibility When using proxy software with fake-ip mode (like Clash), DNS resolves to 198.18.0.0/15 range which is blocked by SSRF guard. This adds allowRfc2544BenchmarkRange policy to web_fetch to support these users. --- src/agents/tools/web-fetch.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/agents/tools/web-fetch.ts b/src/agents/tools/web-fetch.ts index 4ac7a1d7bfd..35d1ef6e471 100644 --- a/src/agents/tools/web-fetch.ts +++ b/src/agents/tools/web-fetch.ts @@ -527,6 +527,9 @@ async function runWebFetch(params: WebFetchRuntimeParams): Promise Date: Mon, 9 Mar 2026 23:04:19 +0800 Subject: [PATCH 3/5] refactor: remove redundant allowRfc2544BenchmarkRange from trusted policy As pointed out by Greptile, dangerouslyAllowPrivateNetwork: true already permits all private network addresses including RFC 2544 range. The allowRfc2544BenchmarkRange flag has no effect when skipPrivateNetworkChecks is true, so it's dead code that could mislead readers. --- src/agents/tools/web-guarded-fetch.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/agents/tools/web-guarded-fetch.ts b/src/agents/tools/web-guarded-fetch.ts index f427eabcab3..2f905a215c0 100644 --- a/src/agents/tools/web-guarded-fetch.ts +++ b/src/agents/tools/web-guarded-fetch.ts @@ -7,7 +7,6 @@ import type { SsrFPolicy } from "../../infra/net/ssrf.js"; const WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY: SsrFPolicy = { dangerouslyAllowPrivateNetwork: true, - allowRfc2544BenchmarkRange: true, }; type WebToolGuardedFetchOptions = Omit & { From eee71ff9a1c41007a15647d3b83b8ff71ca7b668 Mon Sep 17 00:00:00 2001 From: sunkinux Date: Mon, 16 Mar 2026 13:52:19 +0800 Subject: [PATCH 4/5] fix(web-fetch): scope RFC2544 bypass to proxied fetches only Only enable allowRfc2544BenchmarkRange when proxy environment variables are configured. This prevents widening SSRF protections for non-proxied environments while still supporting fake-ip proxy clients like Clash and Surge. Addresses review feedback from Codex and Greptile. --- src/agents/tools/web-fetch.ts | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/agents/tools/web-fetch.ts b/src/agents/tools/web-fetch.ts index 0da9108591f..60bcf5326ab 100644 --- a/src/agents/tools/web-fetch.ts +++ b/src/agents/tools/web-fetch.ts @@ -32,6 +32,25 @@ import { export { extractReadableContent } from "./web-fetch-utils.js"; +const PROXY_ENV_KEYS = [ + "HTTPS_PROXY", + "HTTP_PROXY", + "ALL_PROXY", + "https_proxy", + "http_proxy", + "all_proxy", +] as const; + +function hasProxyEnvConfigured(): boolean { + for (const key of PROXY_ENV_KEYS) { + const value = process.env[key]; + if (typeof value === "string" && value.trim().length > 0) { + return true; + } + } + return false; +} + const EXTRACT_MODES = ["markdown", "text"] as const; const DEFAULT_FETCH_MAX_CHARS = 50_000; @@ -539,9 +558,11 @@ async function runWebFetch(params: WebFetchRuntimeParams): Promise Date: Mon, 16 Mar 2026 14:02:09 +0800 Subject: [PATCH 5/5] style: fix formatting --- src/agents/tools/web-fetch.ts | 4 +--- src/cli/daemon-cli/lifecycle.test.ts | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/agents/tools/web-fetch.ts b/src/agents/tools/web-fetch.ts index 60bcf5326ab..100168f3ed5 100644 --- a/src/agents/tools/web-fetch.ts +++ b/src/agents/tools/web-fetch.ts @@ -560,9 +560,7 @@ async function runWebFetch(params: WebFetchRuntimeParams): Promise 18789); const findVerifiedGatewayListenerPidsOnPortSync = vi.fn<(port: number) => number[]>(() => []); const signalVerifiedGatewayPidSync = vi.fn<(pid: number, signal: "SIGTERM" | "SIGUSR1") => void>(); const formatGatewayPidList = vi.fn<(pids: number[]) => string>((pids) => pids.join(", ")); -const probeGateway = vi.fn< - (opts: { - url: string; - auth?: { token?: string; password?: string }; - timeoutMs: number; - }) => Promise<{ - ok: boolean; - configSnapshot: unknown; - }> ->(); +const probeGateway = + vi.fn< + (opts: { + url: string; + auth?: { token?: string; password?: string }; + timeoutMs: number; + }) => Promise<{ + ok: boolean; + configSnapshot: unknown; + }> + >(); const isRestartEnabled = vi.fn<(config?: { commands?: unknown }) => boolean>(() => true); const loadConfig = vi.fn(() => ({}));