mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 05:47:39 +00:00
fix(security): keep DM pairing allowlists out of group auth
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
import { firstDefined, isSenderIdAllowed, mergeAllowFromSources } from "../channels/allow-from.js";
|
||||
import {
|
||||
firstDefined,
|
||||
isSenderIdAllowed,
|
||||
mergeDmAllowFromSources,
|
||||
} from "../channels/allow-from.js";
|
||||
|
||||
export type NormalizedAllowFrom = {
|
||||
entries: string[];
|
||||
@@ -27,11 +31,11 @@ export const normalizeAllowFrom = (list?: Array<string | number>): NormalizedAll
|
||||
};
|
||||
};
|
||||
|
||||
export const normalizeAllowFromWithStore = (params: {
|
||||
export const normalizeDmAllowFromWithStore = (params: {
|
||||
allowFrom?: Array<string | number>;
|
||||
storeAllowFrom?: string[];
|
||||
dmPolicy?: string;
|
||||
}): NormalizedAllowFrom => normalizeAllowFrom(mergeAllowFromSources(params));
|
||||
}): NormalizedAllowFrom => normalizeAllowFrom(mergeDmAllowFromSources(params));
|
||||
|
||||
export const isSenderAllowed = (params: {
|
||||
allow: NormalizedAllowFrom;
|
||||
|
||||
@@ -182,6 +182,41 @@ describe("handleLineWebhookEvents", () => {
|
||||
expect(processMessage).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("blocks group sender that is only present in pairing-store allowlist", async () => {
|
||||
const processMessage = vi.fn();
|
||||
readAllowFromStoreMock.mockResolvedValueOnce(["user-paired"]);
|
||||
const event = {
|
||||
type: "message",
|
||||
message: { id: "m3b", type: "text", text: "hi" },
|
||||
replyToken: "reply-token",
|
||||
timestamp: Date.now(),
|
||||
source: { type: "group", groupId: "group-1", userId: "user-paired" },
|
||||
mode: "active",
|
||||
webhookEventId: "evt-3b",
|
||||
deliveryContext: { isRedelivery: false },
|
||||
} as MessageEvent;
|
||||
|
||||
await handleLineWebhookEvents([event], {
|
||||
cfg: {
|
||||
channels: { line: { groupPolicy: "allowlist", groupAllowFrom: ["user-owner"] } },
|
||||
},
|
||||
account: {
|
||||
accountId: "default",
|
||||
enabled: true,
|
||||
channelAccessToken: "token",
|
||||
channelSecret: "secret",
|
||||
tokenSource: "config",
|
||||
config: { groupPolicy: "allowlist", groupAllowFrom: ["user-owner"] },
|
||||
},
|
||||
runtime: createRuntime(),
|
||||
mediaMaxBytes: 1,
|
||||
processMessage,
|
||||
});
|
||||
|
||||
expect(buildLineMessageContextMock).not.toHaveBeenCalled();
|
||||
expect(processMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("blocks group messages when wildcard group config disables groups", async () => {
|
||||
const processMessage = vi.fn();
|
||||
const event = {
|
||||
|
||||
@@ -21,7 +21,12 @@ import {
|
||||
upsertChannelPairingRequest,
|
||||
} from "../pairing/pairing-store.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { firstDefined, isSenderAllowed, normalizeAllowFromWithStore } from "./bot-access.js";
|
||||
import {
|
||||
firstDefined,
|
||||
isSenderAllowed,
|
||||
normalizeAllowFrom,
|
||||
normalizeDmAllowFromWithStore,
|
||||
} from "./bot-access.js";
|
||||
import {
|
||||
getLineSourceInfo,
|
||||
buildLineMessageContext,
|
||||
@@ -117,7 +122,7 @@ async function shouldProcessLineEvent(
|
||||
const dmPolicy = account.config.dmPolicy ?? "pairing";
|
||||
|
||||
const storeAllowFrom = await readChannelAllowFromStore("line").catch(() => []);
|
||||
const effectiveDmAllow = normalizeAllowFromWithStore({
|
||||
const effectiveDmAllow = normalizeDmAllowFromWithStore({
|
||||
allowFrom: account.config.allowFrom,
|
||||
storeAllowFrom,
|
||||
dmPolicy,
|
||||
@@ -132,11 +137,9 @@ async function shouldProcessLineEvent(
|
||||
account.config.groupAllowFrom,
|
||||
fallbackGroupAllowFrom,
|
||||
);
|
||||
const effectiveGroupAllow = normalizeAllowFromWithStore({
|
||||
allowFrom: groupAllowFrom,
|
||||
storeAllowFrom,
|
||||
dmPolicy,
|
||||
});
|
||||
// Group authorization stays explicit to group allowlists and must not
|
||||
// inherit DM pairing-store identities.
|
||||
const effectiveGroupAllow = normalizeAllowFrom(groupAllowFrom);
|
||||
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
|
||||
const { groupPolicy, providerMissingFallbackApplied } =
|
||||
resolveAllowlistProviderRuntimeGroupPolicy({
|
||||
|
||||
Reference in New Issue
Block a user