test: expand gateway auth probe coverage

This commit is contained in:
Peter Steinberger
2026-01-16 19:16:03 +00:00
parent c8003ae472
commit 624ff09314
2 changed files with 246 additions and 1 deletions

View File

@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import type { ClawdbotConfig } from "../config/config.js";
import type { ChannelPlugin } from "../channels/plugins/types.js";
@@ -251,6 +251,29 @@ describe("security audit", () => {
);
});
it("adds a warning when deep probe throws", async () => {
const cfg: ClawdbotConfig = { gateway: { mode: "local" } };
const res = await runSecurityAudit({
config: cfg,
deep: true,
deepTimeoutMs: 50,
includeFilesystem: false,
includeChannelSecurity: false,
probeGatewayFn: async () => {
throw new Error("probe boom");
},
});
expect(res.deep?.gateway.ok).toBe(false);
expect(res.deep?.gateway.error).toContain("probe boom");
expect(res.findings).toEqual(
expect.arrayContaining([
expect.objectContaining({ checkId: "gateway.probe_failed", severity: "warn" }),
]),
);
});
it("warns on legacy model configuration", async () => {
const cfg: ClawdbotConfig = {
agents: { defaults: { model: { primary: "openai/gpt-3.5-turbo" } } },
@@ -403,6 +426,27 @@ describe("security audit", () => {
});
describe("maybeProbeGateway auth selection", () => {
const originalEnvToken = process.env.CLAWDBOT_GATEWAY_TOKEN;
const originalEnvPassword = process.env.CLAWDBOT_GATEWAY_PASSWORD;
beforeEach(() => {
delete process.env.CLAWDBOT_GATEWAY_TOKEN;
delete process.env.CLAWDBOT_GATEWAY_PASSWORD;
});
afterEach(() => {
if (originalEnvToken == null) {
delete process.env.CLAWDBOT_GATEWAY_TOKEN;
} else {
process.env.CLAWDBOT_GATEWAY_TOKEN = originalEnvToken;
}
if (originalEnvPassword == null) {
delete process.env.CLAWDBOT_GATEWAY_PASSWORD;
} else {
process.env.CLAWDBOT_GATEWAY_PASSWORD = originalEnvPassword;
}
});
it("uses local auth when gateway.mode is local", async () => {
let capturedAuth: { token?: string; password?: string } | undefined;
const cfg: ClawdbotConfig = {
@@ -437,6 +481,41 @@ describe("security audit", () => {
expect(capturedAuth?.token).toBe("local-token-abc123");
});
it("prefers env token over local config token", async () => {
process.env.CLAWDBOT_GATEWAY_TOKEN = "env-token";
let capturedAuth: { token?: string; password?: string } | undefined;
const cfg: ClawdbotConfig = {
gateway: {
mode: "local",
auth: { token: "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,
};
},
});
expect(capturedAuth?.token).toBe("env-token");
});
it("uses local auth when gateway.mode is undefined (default)", async () => {
let capturedAuth: { token?: string; password?: string } | undefined;
const cfg: ClawdbotConfig = {
@@ -508,6 +587,120 @@ describe("security audit", () => {
expect(capturedAuth?.token).toBe("remote-token-xyz789");
});
it("ignores env token when gateway.mode is remote", async () => {
process.env.CLAWDBOT_GATEWAY_TOKEN = "env-token";
let capturedAuth: { token?: string; password?: string } | undefined;
const cfg: ClawdbotConfig = {
gateway: {
mode: "remote",
auth: { token: "local-token-should-not-use" },
remote: {
url: "ws://remote.example.com:18789",
token: "remote-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,
};
},
});
expect(capturedAuth?.token).toBe("remote-token");
});
it("uses remote password when env is unset", async () => {
let capturedAuth: { token?: string; password?: string } | undefined;
const cfg: ClawdbotConfig = {
gateway: {
mode: "remote",
remote: {
url: "ws://remote.example.com:18789",
password: "remote-pass",
},
},
};
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,
};
},
});
expect(capturedAuth?.password).toBe("remote-pass");
});
it("prefers env password over remote password", async () => {
process.env.CLAWDBOT_GATEWAY_PASSWORD = "env-pass";
let capturedAuth: { token?: string; password?: string } | undefined;
const cfg: ClawdbotConfig = {
gateway: {
mode: "remote",
remote: {
url: "ws://remote.example.com:18789",
password: "remote-pass",
},
},
};
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,
};
},
});
expect(capturedAuth?.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 cfg: ClawdbotConfig = {