From 825cc70796cd839e9d472c48ccae271a325f4328 Mon Sep 17 00:00:00 2001 From: habakan Date: Thu, 19 Feb 2026 20:35:58 +0900 Subject: [PATCH] test: dedupe gateway auth and sessions patch coverage (#20087) --- src/security/audit.test.ts | 624 ++++++++----------------------------- 1 file changed, 135 insertions(+), 489 deletions(-) diff --git a/src/security/audit.test.ts b/src/security/audit.test.ts index 04a1ae9e4d..be46c87aab 100644 --- a/src/security/audit.test.ts +++ b/src/security/audit.test.ts @@ -6,6 +6,7 @@ import type { ChannelPlugin } from "../channels/plugins/types.js"; import type { OpenClawConfig } from "../config/config.js"; import { collectPluginsCodeSafetyFindings } from "./audit-extra.js"; import { runSecurityAudit } from "./audit.js"; +import type { SecurityAuditOptions, SecurityAuditReport } from "./audit.js"; import * as skillScanner from "./skill-scanner.js"; const isWindows = process.platform === "win32"; @@ -72,6 +73,24 @@ function successfulProbeResult(url: string) { }; } +async function audit( + cfg: OpenClawConfig, + extra?: Omit, +): Promise { + return runSecurityAudit({ + config: cfg, + includeFilesystem: false, + includeChannelSecurity: false, + ...extra, + }); +} + +function hasFinding(res: SecurityAuditReport, checkId: string, severity?: string): boolean { + return res.findings.some( + (f) => f.checkId === checkId && (severity == null || f.severity === severity), + ); +} + describe("security audit", () => { let fixtureRoot = ""; let caseId = 0; @@ -82,6 +101,22 @@ describe("security audit", () => { return dir; }; + const withStateDir = async (label: string, fn: (tmp: string) => Promise) => { + const prevStateDir = process.env.OPENCLAW_STATE_DIR; + const tmp = await makeTmpDir(label); + process.env.OPENCLAW_STATE_DIR = tmp; + await fs.mkdir(path.join(tmp, "credentials"), { recursive: true, mode: 0o700 }); + try { + await fn(tmp); + } finally { + if (prevStateDir == null) { + delete process.env.OPENCLAW_STATE_DIR; + } else { + process.env.OPENCLAW_STATE_DIR = prevStateDir; + } + } + }; + beforeAll(async () => { fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-security-audit-")); }); @@ -101,11 +136,7 @@ describe("security audit", () => { browser: { enabled: true }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -129,15 +160,9 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); - expect( - res.findings.some((f) => f.checkId === "gateway.bind_no_auth" && f.severity === "critical"), - ).toBe(true); + expect(hasFinding(res, "gateway.bind_no_auth", "critical")).toBe(true); } finally { // Restore env if (prevToken === undefined) { @@ -161,16 +186,9 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - env: {}, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg, { env: {} }); - expect( - res.findings.some((f) => f.checkId === "gateway.auth_no_rate_limit" && f.severity === "warn"), - ).toBe(true); + expect(hasFinding(res, "gateway.auth_no_rate_limit", "warn")).toBe(true); }); it("warns when gateway.tools.allow re-enables dangerous HTTP /tools/invoke tools (loopback)", async () => { @@ -182,18 +200,9 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - env: {}, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg, { env: {} }); - expect( - res.findings.some( - (f) => f.checkId === "gateway.tools_invoke_http.dangerous_allow" && f.severity === "warn", - ), - ).toBe(true); + expect(hasFinding(res, "gateway.tools_invoke_http.dangerous_allow", "warn")).toBe(true); }); it("flags dangerous gateway.tools.allow over HTTP as critical when gateway binds beyond loopback", async () => { @@ -205,19 +214,9 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - env: {}, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg, { env: {} }); - expect( - res.findings.some( - (f) => - f.checkId === "gateway.tools_invoke_http.dangerous_allow" && f.severity === "critical", - ), - ).toBe(true); + expect(hasFinding(res, "gateway.tools_invoke_http.dangerous_allow", "critical")).toBe(true); }); it("does not warn for auth rate limiting when configured", async () => { @@ -231,14 +230,9 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - env: {}, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg, { env: {} }); - expect(res.findings.some((f) => f.checkId === "gateway.auth_no_rate_limit")).toBe(false); + expect(hasFinding(res, "gateway.auth_no_rate_limit")).toBe(false); }); it("warns when loopback control UI lacks trusted proxies", async () => { @@ -249,11 +243,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -274,12 +264,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - env: {}, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg, { env: {} }); expect(res.findings).toEqual( expect.arrayContaining([ @@ -296,11 +281,7 @@ describe("security audit", () => { logging: { redactSensitive: "off" }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -430,11 +411,7 @@ describe("security audit", () => { browser: { enabled: true }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); const finding = res.findings.find((f) => f.checkId === "models.small_params"); expect(finding?.severity).toBe("critical"); @@ -456,11 +433,7 @@ describe("security audit", () => { browser: { enabled: false }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); const finding = res.findings.find((f) => f.checkId === "models.small_params"); expect(finding?.severity).toBe("info"); @@ -480,11 +453,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -509,13 +478,9 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); - expect(res.findings.some((f) => f.checkId === "sandbox.docker_config_mode_off")).toBe(false); + expect(hasFinding(res, "sandbox.docker_config_mode_off")).toBe(false); }); it("flags dangerous sandbox docker config (binds/network/seccomp/apparmor)", async () => { @@ -535,11 +500,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -569,11 +530,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); const finding = res.findings.find( (f) => f.checkId === "gateway.nodes.deny_commands_ineffective", @@ -598,11 +555,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -623,11 +576,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -650,12 +599,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - env: {}, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg, { env: {} }); expect(res.findings).toEqual( expect.arrayContaining([ @@ -675,14 +619,9 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - env: {}, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg, { env: {} }); - expect(res.findings.some((f) => f.checkId === "browser.control_no_auth")).toBe(false); + expect(hasFinding(res, "browser.control_no_auth")).toBe(false); }); it("warns when remote CDP uses HTTP", async () => { @@ -694,11 +633,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -714,11 +649,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -737,11 +668,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -767,11 +694,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -781,8 +704,8 @@ describe("security audit", () => { }), ]), ); - expect(res.findings.some((f) => f.checkId === "gateway.bind_no_auth")).toBe(false); - expect(res.findings.some((f) => f.checkId === "gateway.auth_no_rate_limit")).toBe(false); + expect(hasFinding(res, "gateway.bind_no_auth")).toBe(false); + expect(hasFinding(res, "gateway.auth_no_rate_limit")).toBe(false); }); it("flags trusted-proxy auth without trustedProxies configured", async () => { @@ -799,11 +722,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -827,11 +746,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -858,11 +773,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -924,11 +835,7 @@ describe("security audit", () => { }); it("flags Discord native commands without a guild user allowlist", async () => { - const prevStateDir = process.env.OPENCLAW_STATE_DIR; - const tmp = await makeTmpDir("discord"); - process.env.OPENCLAW_STATE_DIR = tmp; - await fs.mkdir(path.join(tmp, "credentials"), { recursive: true, mode: 0o700 }); - try { + await withStateDir("discord", async () => { const cfg: OpenClawConfig = { channels: { discord: { @@ -961,21 +868,11 @@ describe("security audit", () => { }), ]), ); - } finally { - if (prevStateDir == null) { - delete process.env.OPENCLAW_STATE_DIR; - } else { - process.env.OPENCLAW_STATE_DIR = prevStateDir; - } - } + }); }); it("does not flag Discord slash commands when dm.allowFrom includes a Discord snowflake id", async () => { - const prevStateDir = process.env.OPENCLAW_STATE_DIR; - const tmp = await makeTmpDir("discord-allowfrom-snowflake"); - process.env.OPENCLAW_STATE_DIR = tmp; - await fs.mkdir(path.join(tmp, "credentials"), { recursive: true, mode: 0o700 }); - try { + await withStateDir("discord-allowfrom-snowflake", async () => { const cfg: OpenClawConfig = { channels: { discord: { @@ -1008,21 +905,11 @@ describe("security audit", () => { }), ]), ); - } finally { - if (prevStateDir == null) { - delete process.env.OPENCLAW_STATE_DIR; - } else { - process.env.OPENCLAW_STATE_DIR = prevStateDir; - } - } + }); }); it("flags Discord slash commands when access-group enforcement is disabled and no users allowlist exists", async () => { - const prevStateDir = process.env.OPENCLAW_STATE_DIR; - const tmp = await makeTmpDir("discord-open"); - process.env.OPENCLAW_STATE_DIR = tmp; - await fs.mkdir(path.join(tmp, "credentials"), { recursive: true, mode: 0o700 }); - try { + await withStateDir("discord-open", async () => { const cfg: OpenClawConfig = { commands: { useAccessGroups: false }, channels: { @@ -1056,21 +943,11 @@ describe("security audit", () => { }), ]), ); - } finally { - if (prevStateDir == null) { - delete process.env.OPENCLAW_STATE_DIR; - } else { - process.env.OPENCLAW_STATE_DIR = prevStateDir; - } - } + }); }); it("flags Slack slash commands without a channel users allowlist", async () => { - const prevStateDir = process.env.OPENCLAW_STATE_DIR; - const tmp = await makeTmpDir("slack"); - process.env.OPENCLAW_STATE_DIR = tmp; - await fs.mkdir(path.join(tmp, "credentials"), { recursive: true, mode: 0o700 }); - try { + await withStateDir("slack", async () => { const cfg: OpenClawConfig = { channels: { slack: { @@ -1098,21 +975,11 @@ describe("security audit", () => { }), ]), ); - } finally { - if (prevStateDir == null) { - delete process.env.OPENCLAW_STATE_DIR; - } else { - process.env.OPENCLAW_STATE_DIR = prevStateDir; - } - } + }); }); it("flags Slack slash commands when access-group enforcement is disabled", async () => { - const prevStateDir = process.env.OPENCLAW_STATE_DIR; - const tmp = await makeTmpDir("slack-open"); - process.env.OPENCLAW_STATE_DIR = tmp; - await fs.mkdir(path.join(tmp, "credentials"), { recursive: true, mode: 0o700 }); - try { + await withStateDir("slack-open", async () => { const cfg: OpenClawConfig = { commands: { useAccessGroups: false }, channels: { @@ -1141,21 +1008,11 @@ describe("security audit", () => { }), ]), ); - } finally { - if (prevStateDir == null) { - delete process.env.OPENCLAW_STATE_DIR; - } else { - process.env.OPENCLAW_STATE_DIR = prevStateDir; - } - } + }); }); it("flags Telegram group commands without a sender allowlist", async () => { - const prevStateDir = process.env.OPENCLAW_STATE_DIR; - const tmp = await makeTmpDir("telegram"); - process.env.OPENCLAW_STATE_DIR = tmp; - await fs.mkdir(path.join(tmp, "credentials"), { recursive: true, mode: 0o700 }); - try { + await withStateDir("telegram", async () => { const cfg: OpenClawConfig = { channels: { telegram: { @@ -1182,21 +1039,11 @@ describe("security audit", () => { }), ]), ); - } finally { - if (prevStateDir == null) { - delete process.env.OPENCLAW_STATE_DIR; - } else { - process.env.OPENCLAW_STATE_DIR = prevStateDir; - } - } + }); }); it("warns when Telegram allowFrom entries are non-numeric (legacy @username configs)", async () => { - const prevStateDir = process.env.OPENCLAW_STATE_DIR; - const tmp = await makeTmpDir("telegram-invalid-allowfrom"); - process.env.OPENCLAW_STATE_DIR = tmp; - await fs.mkdir(path.join(tmp, "credentials"), { recursive: true, mode: 0o700 }); - try { + await withStateDir("telegram-invalid-allowfrom", async () => { const cfg: OpenClawConfig = { channels: { telegram: { @@ -1224,24 +1071,15 @@ describe("security audit", () => { }), ]), ); - } finally { - if (prevStateDir == null) { - delete process.env.OPENCLAW_STATE_DIR; - } else { - process.env.OPENCLAW_STATE_DIR = prevStateDir; - } - } + }); }); it("adds a warning when deep probe fails", async () => { const cfg: OpenClawConfig = { gateway: { mode: "local" } }; - const res = await runSecurityAudit({ - config: cfg, + const res = await audit(cfg, { deep: true, deepTimeoutMs: 50, - includeFilesystem: false, - includeChannelSecurity: false, probeGatewayFn: async () => ({ ok: false, url: "ws://127.0.0.1:18789", @@ -1265,12 +1103,9 @@ describe("security audit", () => { it("adds a warning when deep probe throws", async () => { const cfg: OpenClawConfig = { gateway: { mode: "local" } }; - const res = await runSecurityAudit({ - config: cfg, + const res = await audit(cfg, { deep: true, deepTimeoutMs: 50, - includeFilesystem: false, - includeChannelSecurity: false, probeGatewayFn: async () => { throw new Error("probe boom"); }, @@ -1290,11 +1125,7 @@ describe("security audit", () => { agents: { defaults: { model: { primary: "openai/gpt-3.5-turbo" } } }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -1308,11 +1139,7 @@ describe("security audit", () => { agents: { defaults: { model: { primary: "anthropic/claude-haiku-4-5" } } }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -1327,11 +1154,7 @@ describe("security audit", () => { agents: { defaults: { model: { primary: "venice/claude-opus-45" } } }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); // Should NOT contain weak_tier warning for opus-45 const weakTierFinding = res.findings.find((f) => f.checkId === "models.weak_tier"); @@ -1343,11 +1166,7 @@ describe("security audit", () => { hooks: { enabled: true, token: "short" }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -1364,11 +1183,7 @@ describe("security audit", () => { }; try { - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -1392,11 +1207,7 @@ describe("security audit", () => { hooks: { enabled: true, token: "shared-gateway-token-1234567890" }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -1415,11 +1226,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -1443,11 +1250,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -1471,11 +1274,7 @@ describe("security audit", () => { }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -1490,10 +1289,7 @@ describe("security audit", () => { it("warns when state/config look like a synced folder", async () => { const cfg: OpenClawConfig = {}; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, + const res = await audit(cfg, { stateDir: "/Users/test/Dropbox/.openclaw", configPath: "/Users/test/Dropbox/.openclaw/openclaw.json", }); @@ -1871,11 +1667,7 @@ description: test skill channels: { whatsapp: { groupPolicy: "open" } }, }; - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); + const res = await audit(cfg); expect(res.findings).toEqual( expect.arrayContaining([ @@ -1909,8 +1701,22 @@ description: test skill } }); - it("uses local auth when gateway.mode is local", async () => { + const makeProbeCapture = () => { let capturedAuth: { token?: string; password?: string } | undefined; + return { + probeGatewayFn: async (opts: { + url: string; + auth?: { token?: string; password?: string }; + }) => { + capturedAuth = opts.auth; + return successfulProbeResult(opts.url); + }, + getAuth: () => capturedAuth, + }; + }; + + it("uses local auth when gateway.mode is local", async () => { + const { probeGatewayFn, getAuth } = makeProbeCapture(); const cfg: OpenClawConfig = { gateway: { mode: "local", @@ -1918,34 +1724,14 @@ description: test skill }, }; - await runSecurityAudit({ - config: cfg, - deep: true, - deepTimeoutMs: 50, - includeFilesystem: false, - includeChannelSecurity: false, - probeGatewayFn: async (opts) => { - capturedAuth = opts.auth; - return { - ok: true, - url: opts.url, - connectLatencyMs: 10, - error: null, - close: null, - health: null, - status: null, - presence: null, - configSnapshot: null, - }; - }, - }); + await audit(cfg, { deep: true, deepTimeoutMs: 50, probeGatewayFn }); - expect(capturedAuth?.token).toBe("local-token-abc123"); + expect(getAuth()?.token).toBe("local-token-abc123"); }); it("prefers env token over local config token", async () => { process.env.OPENCLAW_GATEWAY_TOKEN = "env-token"; - let capturedAuth: { token?: string; password?: string } | undefined; + const { probeGatewayFn, getAuth } = makeProbeCapture(); const cfg: OpenClawConfig = { gateway: { mode: "local", @@ -1953,66 +1739,26 @@ description: test skill }, }; - await runSecurityAudit({ - config: cfg, - deep: true, - deepTimeoutMs: 50, - includeFilesystem: false, - includeChannelSecurity: false, - probeGatewayFn: async (opts) => { - capturedAuth = opts.auth; - return { - ok: true, - url: opts.url, - connectLatencyMs: 10, - error: null, - close: null, - health: null, - status: null, - presence: null, - configSnapshot: null, - }; - }, - }); + await audit(cfg, { deep: true, deepTimeoutMs: 50, probeGatewayFn }); - expect(capturedAuth?.token).toBe("env-token"); + expect(getAuth()?.token).toBe("env-token"); }); it("uses local auth when gateway.mode is undefined (default)", async () => { - let capturedAuth: { token?: string; password?: string } | undefined; + const { probeGatewayFn, getAuth } = makeProbeCapture(); const cfg: OpenClawConfig = { gateway: { auth: { token: "default-local-token" }, }, }; - await runSecurityAudit({ - config: cfg, - deep: true, - deepTimeoutMs: 50, - includeFilesystem: false, - includeChannelSecurity: false, - probeGatewayFn: async (opts) => { - capturedAuth = opts.auth; - return { - ok: true, - url: opts.url, - connectLatencyMs: 10, - error: null, - close: null, - health: null, - status: null, - presence: null, - configSnapshot: null, - }; - }, - }); + await audit(cfg, { deep: true, deepTimeoutMs: 50, probeGatewayFn }); - expect(capturedAuth?.token).toBe("default-local-token"); + expect(getAuth()?.token).toBe("default-local-token"); }); it("uses remote auth when gateway.mode is remote with URL", async () => { - let capturedAuth: { token?: string; password?: string } | undefined; + const { probeGatewayFn, getAuth } = makeProbeCapture(); const cfg: OpenClawConfig = { gateway: { mode: "remote", @@ -2024,34 +1770,14 @@ description: test skill }, }; - await runSecurityAudit({ - config: cfg, - deep: true, - deepTimeoutMs: 50, - includeFilesystem: false, - includeChannelSecurity: false, - probeGatewayFn: async (opts) => { - capturedAuth = opts.auth; - return { - ok: true, - url: opts.url, - connectLatencyMs: 10, - error: null, - close: null, - health: null, - status: null, - presence: null, - configSnapshot: null, - }; - }, - }); + await audit(cfg, { deep: true, deepTimeoutMs: 50, probeGatewayFn }); - expect(capturedAuth?.token).toBe("remote-token-xyz789"); + expect(getAuth()?.token).toBe("remote-token-xyz789"); }); it("ignores env token when gateway.mode is remote", async () => { process.env.OPENCLAW_GATEWAY_TOKEN = "env-token"; - let capturedAuth: { token?: string; password?: string } | undefined; + const { probeGatewayFn, getAuth } = makeProbeCapture(); const cfg: OpenClawConfig = { gateway: { mode: "remote", @@ -2063,33 +1789,13 @@ description: test skill }, }; - await runSecurityAudit({ - config: cfg, - deep: true, - deepTimeoutMs: 50, - includeFilesystem: false, - includeChannelSecurity: false, - probeGatewayFn: async (opts) => { - capturedAuth = opts.auth; - return { - ok: true, - url: opts.url, - connectLatencyMs: 10, - error: null, - close: null, - health: null, - status: null, - presence: null, - configSnapshot: null, - }; - }, - }); + await audit(cfg, { deep: true, deepTimeoutMs: 50, probeGatewayFn }); - expect(capturedAuth?.token).toBe("remote-token"); + expect(getAuth()?.token).toBe("remote-token"); }); it("uses remote password when env is unset", async () => { - let capturedAuth: { token?: string; password?: string } | undefined; + const { probeGatewayFn, getAuth } = makeProbeCapture(); const cfg: OpenClawConfig = { gateway: { mode: "remote", @@ -2100,34 +1806,14 @@ description: test skill }, }; - await runSecurityAudit({ - config: cfg, - deep: true, - deepTimeoutMs: 50, - includeFilesystem: false, - includeChannelSecurity: false, - probeGatewayFn: async (opts) => { - capturedAuth = opts.auth; - return { - ok: true, - url: opts.url, - connectLatencyMs: 10, - error: null, - close: null, - health: null, - status: null, - presence: null, - configSnapshot: null, - }; - }, - }); + await audit(cfg, { deep: true, deepTimeoutMs: 50, probeGatewayFn }); - expect(capturedAuth?.password).toBe("remote-pass"); + expect(getAuth()?.password).toBe("remote-pass"); }); it("prefers env password over remote password", async () => { process.env.OPENCLAW_GATEWAY_PASSWORD = "env-pass"; - let capturedAuth: { token?: string; password?: string } | undefined; + const { probeGatewayFn, getAuth } = makeProbeCapture(); const cfg: OpenClawConfig = { gateway: { mode: "remote", @@ -2138,33 +1824,13 @@ description: test skill }, }; - await runSecurityAudit({ - config: cfg, - deep: true, - deepTimeoutMs: 50, - includeFilesystem: false, - includeChannelSecurity: false, - probeGatewayFn: async (opts) => { - capturedAuth = opts.auth; - return { - ok: true, - url: opts.url, - connectLatencyMs: 10, - error: null, - close: null, - health: null, - status: null, - presence: null, - configSnapshot: null, - }; - }, - }); + await audit(cfg, { deep: true, deepTimeoutMs: 50, probeGatewayFn }); - expect(capturedAuth?.password).toBe("env-pass"); + expect(getAuth()?.password).toBe("env-pass"); }); it("falls back to local auth when gateway.mode is remote but URL is missing", async () => { - let capturedAuth: { token?: string; password?: string } | undefined; + const { probeGatewayFn, getAuth } = makeProbeCapture(); const cfg: OpenClawConfig = { gateway: { mode: "remote", @@ -2175,29 +1841,9 @@ description: test skill }, }; - await runSecurityAudit({ - config: cfg, - deep: true, - deepTimeoutMs: 50, - includeFilesystem: false, - includeChannelSecurity: false, - probeGatewayFn: async (opts) => { - capturedAuth = opts.auth; - return { - ok: true, - url: opts.url, - connectLatencyMs: 10, - error: null, - close: null, - health: null, - status: null, - presence: null, - configSnapshot: null, - }; - }, - }); + await audit(cfg, { deep: true, deepTimeoutMs: 50, probeGatewayFn }); - expect(capturedAuth?.token).toBe("fallback-local-token"); + expect(getAuth()?.token).toBe("fallback-local-token"); }); }); });