From eef5e2a55fb02ffc8d9e882faefbbaeaf4a94f01 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 9 May 2026 23:52:31 +0100 Subject: [PATCH] test: tighten security audit assertions --- .../audit-channel-account-metadata.test.ts | 4 +- src/security/audit-channel-dm-policy.test.ts | 46 +++++++++++-------- .../audit-plugin-readonly-scope.test.ts | 44 +++++++++++------- 3 files changed, 55 insertions(+), 39 deletions(-) diff --git a/src/security/audit-channel-account-metadata.test.ts b/src/security/audit-channel-account-metadata.test.ts index 7d9026763c8..1828337a617 100644 --- a/src/security/audit-channel-account-metadata.test.ts +++ b/src/security/audit-channel-account-metadata.test.ts @@ -43,12 +43,10 @@ function requireDangerousMatchingFinding( const finding = findings.find( (entry) => entry.checkId === "channels.discord.allowFrom.dangerous_name_matching_enabled", ); - expect(finding).toMatchObject({ - checkId: "channels.discord.allowFrom.dangerous_name_matching_enabled", - }); if (!finding) { throw new Error("Expected dangerous name matching finding"); } + expect(finding.checkId).toBe("channels.discord.allowFrom.dangerous_name_matching_enabled"); return finding; } diff --git a/src/security/audit-channel-dm-policy.test.ts b/src/security/audit-channel-dm-policy.test.ts index 30bb1442210..5bf40de89f4 100644 --- a/src/security/audit-channel-dm-policy.test.ts +++ b/src/security/audit-channel-dm-policy.test.ts @@ -3,6 +3,19 @@ import type { ChannelPlugin } from "../channels/plugins/types.js"; import type { OpenClawConfig } from "../config/config.js"; import { collectChannelSecurityFindings } from "./audit-channel.js"; +type ChannelSecurityFinding = Awaited>[number]; + +function requireFinding( + findings: ChannelSecurityFinding[], + checkId: string, +): ChannelSecurityFinding { + const finding = findings.find((entry) => entry.checkId === checkId); + if (!finding) { + throw new Error(`Expected finding ${checkId}`); + } + return finding; +} + describe("security audit channel dm policy", () => { it("warns when multiple DM senders share the main session", async () => { const cfg: OpenClawConfig = { @@ -44,14 +57,13 @@ describe("security audit channel dm policy", () => { plugins, }); - expect(findings).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - checkId: "channels.whatsapp.dm.scope_main_multiuser", - severity: "warn", - remediation: expect.stringContaining('config set session.dmScope "per-channel-peer"'), - }), - ]), + const sharedScopeFinding = requireFinding( + findings, + "channels.whatsapp.dm.scope_main_multiuser", + ); + expect(sharedScopeFinding.severity).toBe("warn"); + expect(sharedScopeFinding.remediation).toContain( + 'config set session.dmScope "per-channel-peer"', ); }); @@ -95,17 +107,13 @@ describe("security audit channel dm policy", () => { plugins, }); - expect(findings).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - checkId: "channels.telegram.dm.open", - severity: "critical", - }), - expect.objectContaining({ - checkId: "channels.telegram.dm.scope_main_multiuser", - severity: "warn", - }), - ]), + const openDmFinding = requireFinding(findings, "channels.telegram.dm.open"); + expect(openDmFinding.severity).toBe("critical"); + + const sharedScopeFinding = requireFinding( + findings, + "channels.telegram.dm.scope_main_multiuser", ); + expect(sharedScopeFinding.severity).toBe("warn"); }); }); diff --git a/src/security/audit-plugin-readonly-scope.test.ts b/src/security/audit-plugin-readonly-scope.test.ts index 41a6ed3c18a..19eb94b4167 100644 --- a/src/security/audit-plugin-readonly-scope.test.ts +++ b/src/security/audit-plugin-readonly-scope.test.ts @@ -88,18 +88,27 @@ describe("security audit read-only plugin scope", () => { }), ); - expect(resolveConfiguredChannelPluginIdsMock).toHaveBeenCalledWith( - expect.objectContaining({ - config: sourceConfig, - activationSourceConfig: sourceConfig, - env: {}, - }), - ); - expect(loadPluginMetadataRegistrySnapshotMock).toHaveBeenCalledWith( - expect.objectContaining({ - onlyPluginIds: ["external-channel-plugin", "audit-plugin"], - }), - ); + const resolveConfiguredChannelPluginIdsParams = resolveConfiguredChannelPluginIdsMock.mock + .calls[0]?.[0] as + | { + config?: unknown; + activationSourceConfig?: unknown; + env?: unknown; + } + | undefined; + expect(resolveConfiguredChannelPluginIdsParams?.config).toBe(sourceConfig); + expect(resolveConfiguredChannelPluginIdsParams?.activationSourceConfig).toBe(sourceConfig); + expect(resolveConfiguredChannelPluginIdsParams?.env).toStrictEqual({}); + + const loadSnapshotParams = loadPluginMetadataRegistrySnapshotMock.mock.calls[0]?.[0] as + | { + onlyPluginIds?: string[]; + } + | undefined; + expect(loadSnapshotParams?.onlyPluginIds).toStrictEqual([ + "external-channel-plugin", + "audit-plugin", + ]); }); it("removes configured channel owner collectors only when channel security will audit them", async () => { @@ -125,11 +134,12 @@ describe("security audit read-only plugin scope", () => { }), ); - expect(loadPluginMetadataRegistrySnapshotMock).toHaveBeenCalledWith( - expect.objectContaining({ - onlyPluginIds: ["audit-plugin"], - }), - ); + const loadSnapshotParams = loadPluginMetadataRegistrySnapshotMock.mock.calls[0]?.[0] as + | { + onlyPluginIds?: string[]; + } + | undefined; + expect(loadSnapshotParams?.onlyPluginIds).toStrictEqual(["audit-plugin"]); }); it("skips plugin runtime and collector discovery when collector loading is disabled", async () => {