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
This commit is contained in:
lbo728 2026-03-02 08:12:34 +09:00 committed by Peter Steinberger
parent 08f8aea32e
commit 904016b7de

View File

@ -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);
});
});