From d91ce3d6e0ff3412965dabb2d9410108ef0d63b6 Mon Sep 17 00:00:00 2001 From: dailihui Date: Wed, 4 Mar 2026 22:58:02 +0800 Subject: [PATCH] fix(web-fetch): allow RFC 2544 benchmark range IPs in SSRF guard The web_fetch tool's SSRF protection blocks DNS-resolved IPs in the 198.18.0.0/15 range (RFC 2544 benchmark). This range is commonly used by DNS proxy tools like Clash as fake IPs for transparent proxying. Pass allowRfc2544BenchmarkRange: true to the SSRF policy so that web_fetch does not reject URLs whose DNS resolves to this range, matching the behavior already used by other network-facing components (Telegram, Slack, Discord media, and trusted web tool endpoints). --- src/agents/tools/web-fetch.ssrf.test.ts | 13 +++++++++++++ src/agents/tools/web-fetch.ts | 1 + 2 files changed, 14 insertions(+) diff --git a/src/agents/tools/web-fetch.ssrf.test.ts b/src/agents/tools/web-fetch.ssrf.test.ts index af3d934c208..1dbe128941d 100644 --- a/src/agents/tools/web-fetch.ssrf.test.ts +++ b/src/agents/tools/web-fetch.ssrf.test.ts @@ -130,6 +130,19 @@ describe("web_fetch SSRF protection", () => { expect(fetchSpy).toHaveBeenCalledTimes(1); }); + it("allows RFC 2544 benchmark range IPs (198.18.0.0/15) used by DNS proxy tools", async () => { + lookupMock.mockResolvedValue([{ address: "198.18.1.5", family: 4 }]); + + setMockFetch().mockResolvedValue(textResponse("ok")); + const tool = await createWebFetchToolForTest(); + + const result = await tool?.execute?.("call", { url: "https://example.com" }); + expect(result?.details).toMatchObject({ + status: 200, + extractor: "raw", + }); + }); + it("allows public hosts", async () => { lookupMock.mockResolvedValue([{ address: "93.184.216.34", family: 4 }]); diff --git a/src/agents/tools/web-fetch.ts b/src/agents/tools/web-fetch.ts index 4ac7a1d7bfd..168ad19cbf2 100644 --- a/src/agents/tools/web-fetch.ts +++ b/src/agents/tools/web-fetch.ts @@ -527,6 +527,7 @@ async function runWebFetch(params: WebFetchRuntimeParams): Promise