ai_api / tests /unit /security /live-server-allowlist.test.ts
Yogesh
initial deploy
cd8bd0a
Raw
History Blame Contribute Delete
6.61 kB
/**
* Unit tests for `liveServerAllowList`.
*
* Bug #1 (plans/2026-06-23-omniroute-v3.8.34-deep-audit.md) introduced the
* `LIVE_WS_ALLOWED_HOSTS` opt-in for LAN/Tailscale deployments. These tests
* pin down the contract: defaults remain loopback-only; the env var extends
* the allow-list with bare hostnames or `host:port` pairs; the absence of
* Origin is still only acceptable on loopback.
*
* Runner note: lives under tests/unit/security/ (a node:test–collected subdir)
* and uses node:test + assert/strict so the gate `check:test-discovery` actually
* runs it. The original copy under tests/unit/server/ used vitest in a path no
* runner collected — it never executed (caught by Gate 6A.1).
*/
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import {
buildAllowedOrigins,
buildAllowedHosts,
isOriginAllowed,
originHost,
originHostMatches,
parseCsvEnv,
DEFAULT_ALLOWED_ORIGINS,
} from "@/server/ws/liveServerAllowList";
const EMPTY_ENV: NodeJS.ProcessEnv = {};
describe("parseCsvEnv", () => {
it("returns empty set for undefined", () => {
assert.equal(parseCsvEnv(undefined).size, 0);
});
it("returns empty set for empty string", () => {
assert.equal(parseCsvEnv("").size, 0);
});
it("trims whitespace and drops empty entries", () => {
const out = parseCsvEnv(" a , b ,, c ");
assert.deepEqual([...out], ["a", "b", "c"]);
});
it("deduplicates entries", () => {
const out = parseCsvEnv("a,a,b");
assert.deepEqual([...out], ["a", "b"]);
});
});
describe("buildAllowedOrigins", () => {
it("includes the loopback defaults", () => {
const out = buildAllowedOrigins(EMPTY_ENV);
for (const origin of DEFAULT_ALLOWED_ORIGINS) {
assert.equal(out.has(origin), true);
}
});
it("extends defaults with LIVE_WS_ALLOWED_ORIGINS", () => {
const env = {
...EMPTY_ENV,
LIVE_WS_ALLOWED_ORIGINS: "https://dash.example.com,https://other.example.com",
};
const out = buildAllowedOrigins(env);
assert.equal(out.has("https://dash.example.com"), true);
assert.equal(out.has("https://other.example.com"), true);
// Defaults remain.
assert.equal(out.has("http://localhost:20128"), true);
});
});
describe("buildAllowedHosts", () => {
it("returns empty set when env is not set", () => {
assert.equal(buildAllowedHosts(EMPTY_ENV).size, 0);
});
it("parses comma-separated hosts", () => {
const env = { ...EMPTY_ENV, LIVE_WS_ALLOWED_HOSTS: "100.96.135.160,desktop.tailnet.ts.net" };
const out = buildAllowedHosts(env);
assert.equal(out.has("100.96.135.160"), true);
assert.equal(out.has("desktop.tailnet.ts.net"), true);
});
});
describe("originHost", () => {
it("returns host and hostname for a valid URL", () => {
assert.deepEqual(originHost("http://100.96.135.160:20128"), {
host: "100.96.135.160:20128",
hostname: "100.96.135.160",
});
});
it("returns null for an invalid URL", () => {
assert.equal(originHost("not a url"), null);
});
});
describe("originHostMatches", () => {
it("returns false when the allow-list is empty", () => {
assert.equal(originHostMatches("http://100.96.135.160:20128", new Set()), false);
});
it("matches by exact host:port", () => {
const allow = new Set(["100.96.135.160:20128"]);
assert.equal(originHostMatches("http://100.96.135.160:20128", allow), true);
});
it("matches by bare hostname regardless of port", () => {
const allow = new Set(["100.96.135.160"]);
assert.equal(originHostMatches("http://100.96.135.160:20128", allow), true);
assert.equal(originHostMatches("http://100.96.135.160:55555", allow), true);
});
it("returns false for a non-matching host", () => {
const allow = new Set(["100.96.135.160"]);
assert.equal(originHostMatches("http://10.0.0.5:20128", allow), false);
});
it("returns false for an unparseable origin", () => {
const allow = new Set(["100.96.135.160"]);
assert.equal(originHostMatches("not-a-url", allow), false);
});
});
describe("isOriginAllowed", () => {
it("rejects any non-loopback origin by default", () => {
assert.equal(isOriginAllowed("http://100.96.135.160:20128", EMPTY_ENV), false);
});
it("accepts the default loopback origins", () => {
assert.equal(isOriginAllowed("http://127.0.0.1:20128", EMPTY_ENV), true);
assert.equal(isOriginAllowed("http://localhost:20128", EMPTY_ENV), true);
assert.equal(isOriginAllowed("http://[::1]:20128", EMPTY_ENV), true);
});
it("accepts an Origin matching LIVE_WS_ALLOWED_ORIGINS", () => {
const env = { ...EMPTY_ENV, LIVE_WS_ALLOWED_ORIGINS: "https://dash.example.com" };
assert.equal(isOriginAllowed("https://dash.example.com", env), true);
});
it("accepts a Tailscale Origin when LIVE_WS_ALLOWED_HOSTS is set", () => {
const env = { ...EMPTY_ENV, LIVE_WS_ALLOWED_HOSTS: "100.96.135.160" };
assert.equal(isOriginAllowed("http://100.96.135.160:20128", env), true);
});
it("accepts a Tailscale Origin matched by host:port when LIVE_WS_ALLOWED_HOSTS is set", () => {
const env = { ...EMPTY_ENV, LIVE_WS_ALLOWED_HOSTS: "100.96.135.160:20128" };
assert.equal(isOriginAllowed("http://100.96.135.160:20128", env), true);
});
it("does NOT accept a Tailscale Origin when LIVE_WS_ALLOWED_HOSTS is unset", () => {
// Critical security invariant: without explicit opt-in, the LAN/Tailscale
// surface is closed even though the listener is reachable.
assert.equal(isOriginAllowed("http://100.96.135.160:20128", EMPTY_ENV), false);
});
it("rejects a missing Origin when bound to LAN (0.0.0.0)", () => {
// A CLI client that omits Origin should NOT be accepted when the
// operator opted into LAN exposure. Browsers always send Origin, so the
// empty-Origin path is for non-browser callers; the security stance is
// "refuse unless loopback".
const env = { ...EMPTY_ENV, LIVE_WS_HOST: "0.0.0.0" };
assert.equal(isOriginAllowed(undefined, env), false);
});
it("accepts a missing Origin on loopback (CLI/MCP)", () => {
// CLI/MCP clients running on the same host omit Origin. The default
// listener (127.0.0.1) accepts them.
assert.equal(isOriginAllowed(undefined, EMPTY_ENV), true);
});
it("accepts a missing Origin on ::1 / localhost hosts", () => {
const env1 = { ...EMPTY_ENV, LIVE_WS_HOST: "::1" };
assert.equal(isOriginAllowed(undefined, env1), true);
const env2 = { ...EMPTY_ENV, LIVE_WS_HOST: "localhost" };
assert.equal(isOriginAllowed(undefined, env2), true);
});
});