mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:50:43 +00:00
Gate zalouser startup name matching [AI] (#77411)
* fix: gate zalouser startup name matching * addressing codex review * docs: add changelog entry for PR merge
This commit is contained in:
committed by
GitHub
parent
37c0520a0b
commit
ea75cd8971
@@ -3,7 +3,7 @@ import type { OpenClawConfig, PluginRuntime } from "../runtime-api.js";
|
||||
import "./monitor.send-mocks.js";
|
||||
import "./zalo-js.test-mocks.js";
|
||||
import { resolveZalouserAccountSync } from "./accounts.js";
|
||||
import { __testing } from "./monitor.js";
|
||||
import { __testing, monitorZalouserProvider } from "./monitor.js";
|
||||
import {
|
||||
sendDeliveredZalouserMock,
|
||||
sendMessageZalouserMock,
|
||||
@@ -13,6 +13,11 @@ import {
|
||||
import { setZalouserRuntime } from "./runtime.js";
|
||||
import { createZalouserRuntimeEnv } from "./test-helpers.js";
|
||||
import type { ResolvedZalouserAccount, ZaloInboundMessage } from "./types.js";
|
||||
import {
|
||||
listZaloFriendsMock,
|
||||
listZaloGroupsMock,
|
||||
startZaloListenerMock,
|
||||
} from "./zalo-js.test-mocks.js";
|
||||
|
||||
function createAccount(): ResolvedZalouserAccount {
|
||||
return {
|
||||
@@ -341,6 +346,12 @@ describe("zalouser monitor group mention gating", () => {
|
||||
sendTypingZalouserMock.mockClear();
|
||||
sendDeliveredZalouserMock.mockClear();
|
||||
sendSeenZalouserMock.mockClear();
|
||||
listZaloFriendsMock.mockReset();
|
||||
listZaloFriendsMock.mockResolvedValue([]);
|
||||
listZaloGroupsMock.mockReset();
|
||||
listZaloGroupsMock.mockResolvedValue([]);
|
||||
startZaloListenerMock.mockReset();
|
||||
startZaloListenerMock.mockResolvedValue({ stop: vi.fn() });
|
||||
});
|
||||
|
||||
async function processMessageWithDefaults(params: {
|
||||
@@ -374,6 +385,23 @@ describe("zalouser monitor group mention gating", () => {
|
||||
expect(sendTypingZalouserMock).not.toHaveBeenCalled();
|
||||
}
|
||||
|
||||
async function startMonitorForStartupResolution(
|
||||
accountConfig: ResolvedZalouserAccount["config"],
|
||||
) {
|
||||
installRuntime({ commandAuthorized: false });
|
||||
const abortController = new AbortController();
|
||||
abortController.abort();
|
||||
await monitorZalouserProvider({
|
||||
account: {
|
||||
...createAccount(),
|
||||
config: accountConfig,
|
||||
},
|
||||
config: createConfig(),
|
||||
runtime: createRuntimeEnv(),
|
||||
abortSignal: abortController.signal,
|
||||
});
|
||||
}
|
||||
|
||||
async function expectGroupCommandAuthorizers(params: {
|
||||
accountConfig: ResolvedZalouserAccount["config"];
|
||||
expectedAuthorizers: Array<{ configured: boolean; allowed: boolean }>;
|
||||
@@ -669,6 +697,45 @@ describe("zalouser monitor group mention gating", () => {
|
||||
expect(callArg?.ctx?.To).toBe("zalouser:group:g-attacker-001");
|
||||
});
|
||||
|
||||
it("does not resolve mutable allowlist or group names at startup by default", async () => {
|
||||
listZaloFriendsMock.mockResolvedValue([{ userId: "999", displayName: "Alice" }]);
|
||||
listZaloGroupsMock.mockResolvedValue([{ groupId: "g-other", name: "Trusted Team" }]);
|
||||
|
||||
await startMonitorForStartupResolution({
|
||||
...createAccount().config,
|
||||
dmPolicy: "allowlist",
|
||||
allowFrom: ["Alice"],
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["Alice"],
|
||||
groups: {
|
||||
"Trusted Team": { enabled: true },
|
||||
},
|
||||
});
|
||||
|
||||
expect(listZaloFriendsMock).not.toHaveBeenCalled();
|
||||
expect(listZaloGroupsMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("resolves mutable allowlist and group names at startup when enabled", async () => {
|
||||
listZaloFriendsMock.mockResolvedValue([{ userId: "123", displayName: "Alice" }]);
|
||||
listZaloGroupsMock.mockResolvedValue([{ groupId: "g-trusted", name: "Trusted Team" }]);
|
||||
|
||||
await startMonitorForStartupResolution({
|
||||
...createAccount().config,
|
||||
dangerouslyAllowNameMatching: true,
|
||||
dmPolicy: "allowlist",
|
||||
allowFrom: ["Alice"],
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["Alice"],
|
||||
groups: {
|
||||
"Trusted Team": { enabled: true },
|
||||
},
|
||||
});
|
||||
|
||||
expect(listZaloFriendsMock).toHaveBeenCalledWith("default");
|
||||
expect(listZaloGroupsMock).toHaveBeenCalledWith("default");
|
||||
});
|
||||
|
||||
it("allows group control commands when sender is in groupAllowFrom", async () => {
|
||||
await expectGroupCommandAuthorizers({
|
||||
accountConfig: {
|
||||
|
||||
@@ -828,8 +828,9 @@ export async function monitorZalouserProvider(
|
||||
const groupAllowFromEntries = (account.config.groupAllowFrom ?? [])
|
||||
.map((entry) => normalizeZalouserEntry(String(entry)))
|
||||
.filter((entry) => entry && entry !== "*");
|
||||
const allowNameMatching = isDangerousNameMatchingEnabled(account.config);
|
||||
|
||||
if (allowFromEntries.length > 0 || groupAllowFromEntries.length > 0) {
|
||||
if (allowNameMatching && (allowFromEntries.length > 0 || groupAllowFromEntries.length > 0)) {
|
||||
const friends = await listZaloFriends(profile);
|
||||
const byName = buildNameIndex(friends, (friend) => friend.displayName);
|
||||
if (allowFromEntries.length > 0) {
|
||||
@@ -869,7 +870,7 @@ export async function monitorZalouserProvider(
|
||||
|
||||
const groupsConfig = account.config.groups ?? {};
|
||||
const groupKeys = Object.keys(groupsConfig).filter((key) => key !== "*");
|
||||
if (groupKeys.length > 0) {
|
||||
if (allowNameMatching && groupKeys.length > 0) {
|
||||
const groups = await listZaloGroups(profile);
|
||||
const byName = buildNameIndex(groups, (group) => group.name);
|
||||
const mapping: string[] = [];
|
||||
|
||||
Reference in New Issue
Block a user