Files
openclaw/src/security/audit-channel-readonly-resolution.test.ts
2026-04-06 07:32:12 +01:00

65 lines
1.8 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { ChannelPlugin } from "../channels/plugins/types.js";
import type { OpenClawConfig } from "../config/config.js";
import { collectChannelSecurityFindings } from "./audit-channel.js";
function stubChannelPlugin(params: {
id: "zalouser";
label: string;
resolveAccount: (cfg: OpenClawConfig, accountId: string | null | undefined) => unknown;
}): ChannelPlugin {
return {
id: params.id,
meta: {
id: params.id,
label: params.label,
selectionLabel: params.label,
docsPath: "/docs/testing",
blurb: "test stub",
},
capabilities: {
chatTypes: ["direct", "group"],
},
security: {},
config: {
listAccountIds: () => ["default"],
resolveAccount: (cfg, accountId) => params.resolveAccount(cfg, accountId),
isEnabled: () => true,
isConfigured: () => true,
},
};
}
describe("security audit channel read-only resolution", () => {
it("adds a read-only resolution warning when channel account resolveAccount throws", async () => {
const plugin = stubChannelPlugin({
id: "zalouser",
label: "Zalo Personal",
resolveAccount: () => {
throw new Error("missing SecretRef");
},
});
const cfg: OpenClawConfig = {
channels: {
zalouser: {
enabled: true,
},
},
};
const findings = await collectChannelSecurityFindings({
cfg,
plugins: [plugin],
});
const finding = findings.find(
(entry) => entry.checkId === "channels.zalouser.account.read_only_resolution",
);
expect(finding?.severity).toBe("warn");
expect(finding?.title).toContain("could not be fully resolved");
expect(finding?.detail).toContain("zalouser:default: failed to resolve account");
expect(finding?.detail).toContain("missing SecretRef");
});
});