mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
fix(msteams): enforce sender allowlists with route allowlists
This commit is contained in:
@@ -7,6 +7,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
- Browser/SSRF: block private-network intermediate redirect hops in strict browser navigation flows and fail closed when remote tab-open paths cannot inspect redirect chains. Thanks @zpbrent.
|
- Browser/SSRF: block private-network intermediate redirect hops in strict browser navigation flows and fail closed when remote tab-open paths cannot inspect redirect chains. Thanks @zpbrent.
|
||||||
|
- MS Teams/authz: keep `groupPolicy: "allowlist"` enforcing sender allowlists even when a team/channel route allowlist is configured, so route matches no longer widen group access to every sender in that route. Thanks @zpbrent.
|
||||||
|
|
||||||
## 2026.3.8
|
## 2026.3.8
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { setMSTeamsRuntime } from "../runtime.js";
|
|||||||
import { createMSTeamsMessageHandler } from "./message-handler.js";
|
import { createMSTeamsMessageHandler } from "./message-handler.js";
|
||||||
|
|
||||||
describe("msteams monitor handler authz", () => {
|
describe("msteams monitor handler authz", () => {
|
||||||
it("does not treat DM pairing-store entries as group allowlist entries", async () => {
|
function createDeps(cfg: OpenClawConfig) {
|
||||||
const readAllowFromStore = vi.fn(async () => ["attacker-aad"]);
|
const readAllowFromStore = vi.fn(async () => ["attacker-aad"]);
|
||||||
setMSTeamsRuntime({
|
setMSTeamsRuntime({
|
||||||
logging: { shouldLogVerbose: () => false },
|
logging: { shouldLogVerbose: () => false },
|
||||||
@@ -35,16 +35,7 @@ describe("msteams monitor handler authz", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const deps: MSTeamsMessageHandlerDeps = {
|
const deps: MSTeamsMessageHandlerDeps = {
|
||||||
cfg: {
|
cfg,
|
||||||
channels: {
|
|
||||||
msteams: {
|
|
||||||
dmPolicy: "pairing",
|
|
||||||
allowFrom: [],
|
|
||||||
groupPolicy: "allowlist",
|
|
||||||
groupAllowFrom: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as OpenClawConfig,
|
|
||||||
runtime: { error: vi.fn() } as unknown as RuntimeEnv,
|
runtime: { error: vi.fn() } as unknown as RuntimeEnv,
|
||||||
appId: "test-app",
|
appId: "test-app",
|
||||||
adapter: {} as MSTeamsMessageHandlerDeps["adapter"],
|
adapter: {} as MSTeamsMessageHandlerDeps["adapter"],
|
||||||
@@ -65,6 +56,21 @@ describe("msteams monitor handler authz", () => {
|
|||||||
} as unknown as MSTeamsMessageHandlerDeps["log"],
|
} as unknown as MSTeamsMessageHandlerDeps["log"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return { conversationStore, deps, readAllowFromStore };
|
||||||
|
}
|
||||||
|
|
||||||
|
it("does not treat DM pairing-store entries as group allowlist entries", async () => {
|
||||||
|
const { conversationStore, deps, readAllowFromStore } = createDeps({
|
||||||
|
channels: {
|
||||||
|
msteams: {
|
||||||
|
dmPolicy: "pairing",
|
||||||
|
allowFrom: [],
|
||||||
|
groupPolicy: "allowlist",
|
||||||
|
groupAllowFrom: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as OpenClawConfig);
|
||||||
|
|
||||||
const handler = createMSTeamsMessageHandler(deps);
|
const handler = createMSTeamsMessageHandler(deps);
|
||||||
await handler({
|
await handler({
|
||||||
activity: {
|
activity: {
|
||||||
@@ -96,4 +102,54 @@ describe("msteams monitor handler authz", () => {
|
|||||||
});
|
});
|
||||||
expect(conversationStore.upsert).not.toHaveBeenCalled();
|
expect(conversationStore.upsert).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not widen sender auth when only a teams route allowlist is configured", async () => {
|
||||||
|
const { conversationStore, deps } = createDeps({
|
||||||
|
channels: {
|
||||||
|
msteams: {
|
||||||
|
dmPolicy: "pairing",
|
||||||
|
allowFrom: [],
|
||||||
|
groupPolicy: "allowlist",
|
||||||
|
groupAllowFrom: [],
|
||||||
|
teams: {
|
||||||
|
team123: {
|
||||||
|
channels: {
|
||||||
|
"19:group@thread.tacv2": { requireMention: false },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as OpenClawConfig);
|
||||||
|
|
||||||
|
const handler = createMSTeamsMessageHandler(deps);
|
||||||
|
await handler({
|
||||||
|
activity: {
|
||||||
|
id: "msg-1",
|
||||||
|
type: "message",
|
||||||
|
text: "hello",
|
||||||
|
from: {
|
||||||
|
id: "attacker-id",
|
||||||
|
aadObjectId: "attacker-aad",
|
||||||
|
name: "Attacker",
|
||||||
|
},
|
||||||
|
recipient: {
|
||||||
|
id: "bot-id",
|
||||||
|
name: "Bot",
|
||||||
|
},
|
||||||
|
conversation: {
|
||||||
|
id: "19:group@thread.tacv2",
|
||||||
|
conversationType: "groupChat",
|
||||||
|
},
|
||||||
|
channelData: {
|
||||||
|
team: { id: "team123", name: "Team 123" },
|
||||||
|
channel: { name: "General" },
|
||||||
|
},
|
||||||
|
attachments: [],
|
||||||
|
},
|
||||||
|
sendActivity: vi.fn(async () => undefined),
|
||||||
|
} as unknown as Parameters<typeof handler>[0]);
|
||||||
|
|
||||||
|
expect(conversationStore.upsert).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -242,10 +242,7 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
|
|||||||
}
|
}
|
||||||
const senderGroupAccess = evaluateSenderGroupAccessForPolicy({
|
const senderGroupAccess = evaluateSenderGroupAccessForPolicy({
|
||||||
groupPolicy,
|
groupPolicy,
|
||||||
groupAllowFrom:
|
groupAllowFrom: effectiveGroupAllowFrom,
|
||||||
effectiveGroupAllowFrom.length > 0 || !channelGate.allowlistConfigured
|
|
||||||
? effectiveGroupAllowFrom
|
|
||||||
: ["*"],
|
|
||||||
senderId,
|
senderId,
|
||||||
isSenderAllowed: (_senderId, allowFrom) =>
|
isSenderAllowed: (_senderId, allowFrom) =>
|
||||||
resolveMSTeamsAllowlistMatch({
|
resolveMSTeamsAllowlistMatch({
|
||||||
|
|||||||
Reference in New Issue
Block a user