From 904016b7de43ec490eb53ec3d91295f5a5192263 Mon Sep 17 00:00:00 2001 From: lbo728 Date: Mon, 2 Mar 2026 08:12:34 +0900 Subject: [PATCH] fix(origin-check): honour "*" wildcard in gateway.controlUi.allowedOrigins When gateway.controlUi.allowedOrigins is set to ["*"], the Control UI WebSocket was still rejected with "origin not allowed" for any non- loopback origin (e.g. Tailscale IPs, LAN addresses). Root cause: checkBrowserOrigin() compared each allowedOrigins entry against the parsed request origin via a literal Array#includes(). The entry "*" never equals an actual origin string, so the wildcard was silently ignored and all remote connections were blocked. Fix: check for the literal "*" entry before the per-origin comparison and return ok:true immediately when found. Closes #30990 --- src/gateway/origin-check.test.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/gateway/origin-check.test.ts b/src/gateway/origin-check.test.ts index e0dd33a80f2..0797d6c4066 100644 --- a/src/gateway/origin-check.test.ts +++ b/src/gateway/origin-check.test.ts @@ -60,4 +60,31 @@ describe("checkBrowserOrigin", () => { }); expect(result.ok).toBe(false); }); + + it('accepts any origin when allowedOrigins includes "*" (regression: #30990)', () => { + const result = checkBrowserOrigin({ + requestHost: "100.86.79.37:18789", + origin: "https://100.86.79.37:18789", + allowedOrigins: ["*"], + }); + expect(result.ok).toBe(true); + }); + + it('accepts any origin when allowedOrigins includes "*" alongside specific entries', () => { + const result = checkBrowserOrigin({ + requestHost: "gateway.tailnet.ts.net:18789", + origin: "https://gateway.tailnet.ts.net:18789", + allowedOrigins: ["https://control.example.com", "*"], + }); + expect(result.ok).toBe(true); + }); + + it('accepts wildcard entries with surrounding whitespace', () => { + const result = checkBrowserOrigin({ + requestHost: "100.86.79.37:18789", + origin: "https://100.86.79.37:18789", + allowedOrigins: [" * "], + }); + expect(result.ok).toBe(true); + }); });