From 4d9955dd587825678b9878c4c7490e7f9c5809e6 Mon Sep 17 00:00:00 2001 From: gegemeimingzi Date: Tue, 18 Aug 2026 11:10:36 +0800 Subject: [PATCH] fix(opencode): route webfetch through the WebFetch redirect (#1052) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenCode registers its fetch tool as `webfetch`, but TOOL_ALIASES only mapped `fetch`. The alias lookup missed, `canonical` stayed `webfetch`, and the WebFetch redirect branch never matched — the tool executed as a plain allow with zero routing interception. Add the `webfetch: WebFetch` alias so opencode fetch calls are denied and redirected to ctx_fetch_and_index / ctx_search like every other platform's WebFetch. TDD: new test in tests/hooks/core-routing.test.ts (WebFetch domain) failed before the alias (null result), passes after (deny + redirect reason). Real-path check: compiled opencode plugin's tool.execute.before throws the redirect error for a webfetch payload with the alias, and passes through without it. --- hooks/core/routing.mjs | 1 + tests/hooks/core-routing.test.ts | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/hooks/core/routing.mjs b/hooks/core/routing.mjs index e92ab46b2..c8a1b4181 100644 --- a/hooks/core/routing.mjs +++ b/hooks/core/routing.mjs @@ -532,6 +532,7 @@ const TOOL_ALIASES = { "view": "Read", "grep": "Grep", "fetch": "WebFetch", + "webfetch": "WebFetch", "agent": "Agent", // Codex CLI "shell": "Bash", diff --git a/tests/hooks/core-routing.test.ts b/tests/hooks/core-routing.test.ts index 310c94d8f..ae4cf0193 100644 --- a/tests/hooks/core-routing.test.ts +++ b/tests/hooks/core-routing.test.ts @@ -490,6 +490,22 @@ describe("routePreToolUse", () => { expect(subagent.status).toBe(0); expect(subagent.stdout).toBe(""); }); + + it("treats opencode webfetch as WebFetch and blocks it (#1052)", () => { + const url = "https://example.com"; + const result = routePreToolUse( + "webfetch", + { url }, + undefined, + "opencode", + "opencode-webfetch", + ); + expect(result).not.toBeNull(); + expect(result!.action).toBe("deny"); + expect(result!.reason).toContain("WebFetch redirected"); + expect(result!.reason).toContain("fetch_and_index"); + expect(result!.reason).toContain("ctx_search"); + }); }); // ─── MCP readiness: all redirects degrade gracefully (#230) ───