mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-13 10:11:20 +00:00
Security: inject channel config-fix plugins in tests
This commit is contained in:
@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||
import type { ChannelPlugin } from "../channels/plugins/types.js";
|
||||
import { fixSecurityFootguns } from "./fix.js";
|
||||
|
||||
const isWindows = process.platform === "win32";
|
||||
@@ -30,6 +31,70 @@ describe("security fix", () => {
|
||||
OPENCLAW_CONFIG_PATH: configPath,
|
||||
});
|
||||
|
||||
const createWhatsAppConfigFixTestPlugin = (storeAllowFrom: string[]): ChannelPlugin => ({
|
||||
id: "whatsapp",
|
||||
meta: {
|
||||
id: "whatsapp",
|
||||
label: "WhatsApp",
|
||||
selectionLabel: "WhatsApp",
|
||||
docsPath: "/docs/testing",
|
||||
blurb: "test stub",
|
||||
},
|
||||
capabilities: {
|
||||
chatTypes: ["direct", "group"],
|
||||
},
|
||||
config: {
|
||||
listAccountIds: () => ["default"],
|
||||
inspectAccount: () => ({ accountId: "default", enabled: true, configured: true, config: {} }),
|
||||
resolveAccount: () => ({ accountId: "default", enabled: true, config: {} }),
|
||||
isEnabled: () => true,
|
||||
isConfigured: () => true,
|
||||
},
|
||||
security: {
|
||||
applyConfigFixes: async ({ cfg }) => {
|
||||
if (storeAllowFrom.length === 0) {
|
||||
return { config: cfg, changes: [] };
|
||||
}
|
||||
const next = structuredClone(cfg ?? {});
|
||||
const whatsapp = next.channels?.whatsapp as Record<string, unknown> | undefined;
|
||||
if (!whatsapp || typeof whatsapp !== "object") {
|
||||
return { config: cfg, changes: [] };
|
||||
}
|
||||
const changes: string[] = [];
|
||||
let changed = false;
|
||||
const maybeApply = (prefix: string, holder: Record<string, unknown>) => {
|
||||
if (holder.groupPolicy !== "allowlist") {
|
||||
return;
|
||||
}
|
||||
const allowFrom = Array.isArray(holder.allowFrom) ? holder.allowFrom : [];
|
||||
const groupAllowFrom = Array.isArray(holder.groupAllowFrom) ? holder.groupAllowFrom : [];
|
||||
if (allowFrom.length > 0 || groupAllowFrom.length > 0) {
|
||||
return;
|
||||
}
|
||||
holder.groupAllowFrom = [...storeAllowFrom];
|
||||
changes.push(`${prefix}groupAllowFrom=pairing-store`);
|
||||
changed = true;
|
||||
};
|
||||
|
||||
maybeApply("channels.whatsapp.", whatsapp);
|
||||
const accounts = whatsapp.accounts;
|
||||
if (accounts && typeof accounts === "object") {
|
||||
for (const [accountId, value] of Object.entries(accounts)) {
|
||||
if (!value || typeof value !== "object") {
|
||||
continue;
|
||||
}
|
||||
maybeApply(
|
||||
`channels.whatsapp.accounts.${accountId}.`,
|
||||
value as Record<string, unknown>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return { config: changed ? next : cfg, changes };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const writeJsonConfig = async (configPath: string, config: Record<string, unknown>) => {
|
||||
await fs.writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
|
||||
};
|
||||
@@ -45,9 +110,13 @@ describe("security fix", () => {
|
||||
const readParsedConfig = async (configPath: string) =>
|
||||
JSON.parse(await fs.readFile(configPath, "utf-8")) as Record<string, unknown>;
|
||||
|
||||
const runFixAndReadChannels = async (stateDir: string, configPath: string) => {
|
||||
const runFixAndReadChannels = async (
|
||||
stateDir: string,
|
||||
configPath: string,
|
||||
channelPlugins?: ChannelPlugin[],
|
||||
) => {
|
||||
const env = createFixEnv(stateDir, configPath);
|
||||
const res = await fixSecurityFootguns({ env, stateDir, configPath });
|
||||
const res = await fixSecurityFootguns({ env, stateDir, configPath, channelPlugins });
|
||||
const parsed = await readParsedConfig(configPath);
|
||||
return {
|
||||
res,
|
||||
@@ -71,7 +140,9 @@ describe("security fix", () => {
|
||||
}) => {
|
||||
await writeWhatsAppConfig(params.configPath, params.whatsapp);
|
||||
await writeWhatsAppAllowFromStore(params.stateDir, params.allowFromStore);
|
||||
return runFixAndReadChannels(params.stateDir, params.configPath);
|
||||
return runFixAndReadChannels(params.stateDir, params.configPath, [
|
||||
createWhatsAppConfigFixTestPlugin(params.allowFromStore),
|
||||
]);
|
||||
};
|
||||
|
||||
const writeWhatsAppAllowFromStore = async (stateDir: string, allowFrom: string[]) => {
|
||||
@@ -148,7 +219,12 @@ describe("security fix", () => {
|
||||
await writeWhatsAppAllowFromStore(stateDir, [" +15551234567 "]);
|
||||
const env = createFixEnv(stateDir, configPath);
|
||||
|
||||
const res = await fixSecurityFootguns({ env, stateDir, configPath });
|
||||
const res = await fixSecurityFootguns({
|
||||
env,
|
||||
stateDir,
|
||||
configPath,
|
||||
channelPlugins: [createWhatsAppConfigFixTestPlugin(["+15551234567"])],
|
||||
});
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.configWritten).toBe(true);
|
||||
expect(res.changes).toEqual(
|
||||
|
||||
@@ -248,10 +248,14 @@ function applyConfigFixes(params: { cfg: OpenClawConfig; env: NodeJS.ProcessEnv
|
||||
async function collectChannelSecurityConfigFixMutation(params: {
|
||||
cfg: OpenClawConfig;
|
||||
env: NodeJS.ProcessEnv;
|
||||
channelPlugins?: ChannelPlugin[];
|
||||
}) {
|
||||
let nextCfg = params.cfg;
|
||||
const changes: string[] = [];
|
||||
const collectPlugins = (): ChannelPlugin[] => {
|
||||
if (params.channelPlugins) {
|
||||
return params.channelPlugins;
|
||||
}
|
||||
try {
|
||||
const pluginIds = Object.keys(params.cfg.channels ?? {}).filter(Boolean);
|
||||
if (pluginIds.length === 0) {
|
||||
@@ -358,6 +362,7 @@ export async function fixSecurityFootguns(opts?: {
|
||||
configPath?: string;
|
||||
platform?: NodeJS.Platform;
|
||||
exec?: ExecFn;
|
||||
channelPlugins?: ChannelPlugin[];
|
||||
}): Promise<SecurityFixResult> {
|
||||
const env = opts?.env ?? process.env;
|
||||
const platform = opts?.platform ?? process.platform;
|
||||
@@ -381,6 +386,7 @@ export async function fixSecurityFootguns(opts?: {
|
||||
const channelFixes = await collectChannelSecurityConfigFixMutation({
|
||||
cfg: fixed.cfg,
|
||||
env,
|
||||
channelPlugins: opts?.channelPlugins,
|
||||
});
|
||||
changes = [...fixed.changes, ...channelFixes.changes];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user