From 98579f98c1db51668875352a14c016dd0fb32e94 Mon Sep 17 00:00:00 2001 From: Sutarto Jordan Chrisfivo Date: Thu, 3 Sep 2026 09:28:56 +0700 Subject: [PATCH] fix(auth): protect root /responses rewrite Add /responses to PUBLIC_PREFIXES in dashboardGuard so pre-rewrite remote requests require API key validation as intended. --- src/dashboardGuard.js | 3 ++- tests/unit/dashboard-guard.test.js | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/dashboardGuard.js b/src/dashboardGuard.js index 1c6a4483..3d4b2e32 100644 --- a/src/dashboardGuard.js +++ b/src/dashboardGuard.js @@ -34,7 +34,8 @@ const PUBLIC_API_PATHS = [ ]; // Public top-level prefixes (LLM API endpoints with their own API key auth). -const PUBLIC_PREFIXES = ["/v1", "/v1beta", "/api/v1", "/api/v1beta", "/codex"]; +// Keep root-level rewrites here too: middleware runs before Next.js rewrites. +const PUBLIC_PREFIXES = ["/v1", "/v1beta", "/api/v1", "/api/v1beta", "/codex", "/responses"]; // Always require JWT token regardless of requireLogin setting const ALWAYS_PROTECTED = [ diff --git a/tests/unit/dashboard-guard.test.js b/tests/unit/dashboard-guard.test.js index fd30e4b2..931f689e 100644 --- a/tests/unit/dashboard-guard.test.js +++ b/tests/unit/dashboard-guard.test.js @@ -125,6 +125,25 @@ describe("dashboard guard public LLM API access", () => { expect(response.body.error).toBe("API key required for remote API access"); }); + it("rejects remote /responses rewrite without API key", async () => { + const response = await proxy(request("/responses", { host: "router.example.com" })); + + expect(response.status).toBe(401); + expect(response.body.error).toBe("API key required for remote API access"); + }); + + it("allows remote /responses rewrite with a valid API key", async () => { + mocks.validateApiKey.mockResolvedValue(true); + + const response = await proxy(request("/responses", { + host: "router.example.com", + authorization: "Bearer sk-valid", + })); + + expect(response).toBe(mocks.nextResponse); + expect(mocks.validateApiKey).toHaveBeenCalledWith("sk-valid"); + }); + it("allows remote codex rewrite with valid API key", async () => { mocks.validateApiKey.mockResolvedValue(true);