import { describe, expect, it } from "vitest" ;
import type { OpenClawConfig } from "../config/config.js" ;
import { resolveGatewayProbeAuthSafe, resolveGatewayProbeTarget } from "../gateway/probe-auth.js" ;
import { collectDeepProbeFindings } from "./audit-deep-probe-findings.js" ;
describe("security audit gateway auth selection" , () => {
it("applies gateway auth precedence across local and remote modes" , async () => {
const makeProbeEnv = (env?: { token?: string; password?: string }) => {
const probeEnv: NodeJS.ProcessEnv = {};
if (env?.token !== undefined) {
probeEnv.OPENCLAW_GATEWAY_TOKEN = env.token;
}
if (env?.password !== undefined) {
probeEnv.OPENCLAW_GATEWAY_PASSWORD = env.password;
}
return probeEnv;
};
const cases: Array<{
name: string;
cfg: OpenClawConfig;
env?: { token?: string; password?: string };
expectedAuth: { token?: string; password?: string };
}> = [
{
name: "uses local auth when gateway.mode is local" ,
cfg: { gateway: { mode: "local" , auth: { token: "local-token-abc123" } } },
expectedAuth: { token: "local-token-abc123" },
},
{
name: "prefers env token over local config token" ,
cfg: { gateway: { mode: "local" , auth: { token: "local-token" } } },
env: { token: "env-token" },
expectedAuth: { token: "env-token" },
},
{
name: "uses local auth when gateway.mode is undefined (default)" ,
cfg: { gateway: { auth: { token: "default-local-token" } } },
expectedAuth: { token: "default-local-token" },
},
{
name: "uses remote auth when gateway.mode is remote with URL" ,
cfg: {
gateway: {
mode: "remote" ,
auth: { token: "local-token-should-not-use" },
remote: { url: "wss://remote.example.com:18789", token: "remote-token-xyz789" },
},
},
expectedAuth: { token: "remote-token-xyz789" },
},
{
name: "ignores env token when gateway.mode is remote" ,
cfg: {
gateway: {
mode: "remote" ,
auth: { token: "local-token-should-not-use" },
remote: { url: "wss://remote.example.com:18789", token: "remote-token" },
},
},
env: { token: "env-token" },
expectedAuth: { token: "remote-token" },
},
{
name: "falls back to local auth when gateway.mode is remote but URL is missing" ,
cfg: {
gateway: {
mode: "remote" ,
auth: { token: "fallback-local-token" },
remote: { token: "remote-token-should-not-use" },
},
},
expectedAuth: { token: "fallback-local-token" },
},
{
name: "uses remote password when env is unset" ,
cfg: {
gateway: {
mode: "remote" ,
remote: { url: "wss://remote.example.com:18789", password: "remote-pass" },
},
},
expectedAuth: { password: "remote-pass" },
},
{
name: "prefers env password over remote password" ,
cfg: {
gateway: {
mode: "remote" ,
remote: { url: "wss://remote.example.com:18789", password: "remote-pass" },
},
},
env: { password: "env-pass" },
expectedAuth: { password: "env-pass" },
},
];
await Promise.all(
cases.map(async (testCase) => {
const target = resolveGatewayProbeTarget(testCase.cfg);
const result = resolveGatewayProbeAuthSafe({
cfg: testCase.cfg,
env: makeProbeEnv(testCase.env),
mode: target.mode,
});
expect(result.auth, testCase.name).toEqual(testCase.expectedAuth);
}),
);
});
it("adds warning finding when probe auth SecretRef is unavailable" , () => {
const cfg: OpenClawConfig = {
gateway: {
mode: "local" ,
auth: {
mode: "token" ,
token: { source: "env" , provider: "default" , id: "MISSING_GATEWAY_TOKEN" },
},
},
secrets: {
providers: {
default : { source: "env" },
},
},
};
const result = resolveGatewayProbeAuthSafe({
cfg,
mode: "local" ,
env: {},
});
const warning = collectDeepProbeFindings({
deep: {
gateway: {
attempted: true ,
url: "ws://127.0.0.1:18789",
ok: true ,
error: null ,
close: null ,
},
},
authWarning: result.warning,
}).find((finding) => finding.checkId === "gateway.probe_auth_secretref_unavailable" );
expect(warning?.severity).toBe("warn" );
expect(warning?.detail).toContain("gateway.auth.token" );
});
});
Messung V0.5 in Prozent C=93 H=91 G=91
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-05)
¤
*© Formatika GbR, Deutschland