@openclaw/msteams 2026.3.10 → 2026.3.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.3.12
4
+
5
+ ### Changes
6
+
7
+ - Version alignment with core OpenClaw release numbers.
8
+
9
+ ## 2026.3.11
10
+
11
+ ### Changes
12
+
13
+ - Version alignment with core OpenClaw release numbers.
14
+
3
15
  ## 2026.3.10
4
16
 
5
17
  ### Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/msteams",
3
- "version": "2026.3.10",
3
+ "version": "2026.3.12",
4
4
  "description": "OpenClaw Microsoft Teams channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -175,6 +175,7 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
175
175
  teamName,
176
176
  conversationId,
177
177
  channelName,
178
+ allowNameMatching: isDangerousNameMatchingEnabled(msteamsCfg),
178
179
  });
179
180
  const senderGroupPolicy = resolveSenderScopedGroupPolicy({
180
181
  groupPolicy,
@@ -50,7 +50,7 @@ describe("msteams policy", () => {
50
50
  expect(res.allowed).toBe(false);
51
51
  });
52
52
 
53
- it("matches team and channel by name", () => {
53
+ it("blocks team and channel name matches by default", () => {
54
54
  const cfg: MSTeamsConfig = {
55
55
  teams: {
56
56
  "My Team": {
@@ -69,6 +69,31 @@ describe("msteams policy", () => {
69
69
  conversationId: "ignored",
70
70
  });
71
71
 
72
+ expect(res.teamConfig).toBeUndefined();
73
+ expect(res.channelConfig).toBeUndefined();
74
+ expect(res.allowed).toBe(false);
75
+ });
76
+
77
+ it("matches team and channel by name when dangerous name matching is enabled", () => {
78
+ const cfg: MSTeamsConfig = {
79
+ teams: {
80
+ "My Team": {
81
+ requireMention: true,
82
+ channels: {
83
+ "General Chat": { requireMention: false },
84
+ },
85
+ },
86
+ },
87
+ };
88
+
89
+ const res = resolveMSTeamsRouteConfig({
90
+ cfg,
91
+ teamName: "My Team",
92
+ channelName: "General Chat",
93
+ conversationId: "ignored",
94
+ allowNameMatching: true,
95
+ });
96
+
72
97
  expect(res.teamConfig?.requireMention).toBe(true);
73
98
  expect(res.channelConfig?.requireMention).toBe(false);
74
99
  expect(res.allowed).toBe(true);
package/src/policy.ts CHANGED
@@ -16,6 +16,7 @@ import {
16
16
  resolveToolsBySender,
17
17
  resolveChannelEntryMatchWithFallback,
18
18
  resolveNestedAllowlistDecision,
19
+ isDangerousNameMatchingEnabled,
19
20
  } from "openclaw/plugin-sdk/msteams";
20
21
 
21
22
  export type MSTeamsResolvedRouteConfig = {
@@ -35,6 +36,7 @@ export function resolveMSTeamsRouteConfig(params: {
35
36
  teamName?: string | null | undefined;
36
37
  conversationId?: string | null | undefined;
37
38
  channelName?: string | null | undefined;
39
+ allowNameMatching?: boolean;
38
40
  }): MSTeamsResolvedRouteConfig {
39
41
  const teamId = params.teamId?.trim();
40
42
  const teamName = params.teamName?.trim();
@@ -44,8 +46,8 @@ export function resolveMSTeamsRouteConfig(params: {
44
46
  const allowlistConfigured = Object.keys(teams).length > 0;
45
47
  const teamCandidates = buildChannelKeyCandidates(
46
48
  teamId,
47
- teamName,
48
- teamName ? normalizeChannelSlug(teamName) : undefined,
49
+ params.allowNameMatching ? teamName : undefined,
50
+ params.allowNameMatching && teamName ? normalizeChannelSlug(teamName) : undefined,
49
51
  );
50
52
  const teamMatch = resolveChannelEntryMatchWithFallback({
51
53
  entries: teams,
@@ -58,8 +60,8 @@ export function resolveMSTeamsRouteConfig(params: {
58
60
  const channelAllowlistConfigured = Object.keys(channels).length > 0;
59
61
  const channelCandidates = buildChannelKeyCandidates(
60
62
  conversationId,
61
- channelName,
62
- channelName ? normalizeChannelSlug(channelName) : undefined,
63
+ params.allowNameMatching ? channelName : undefined,
64
+ params.allowNameMatching && channelName ? normalizeChannelSlug(channelName) : undefined,
63
65
  );
64
66
  const channelMatch = resolveChannelEntryMatchWithFallback({
65
67
  entries: channels,
@@ -101,6 +103,7 @@ export function resolveMSTeamsGroupToolPolicy(
101
103
  const groupId = params.groupId?.trim();
102
104
  const groupChannel = params.groupChannel?.trim();
103
105
  const groupSpace = params.groupSpace?.trim();
106
+ const allowNameMatching = isDangerousNameMatchingEnabled(cfg);
104
107
 
105
108
  const resolved = resolveMSTeamsRouteConfig({
106
109
  cfg,
@@ -108,6 +111,7 @@ export function resolveMSTeamsGroupToolPolicy(
108
111
  teamName: groupSpace,
109
112
  conversationId: groupId,
110
113
  channelName: groupChannel,
114
+ allowNameMatching,
111
115
  });
112
116
 
113
117
  if (resolved.channelConfig) {
@@ -158,8 +162,8 @@ export function resolveMSTeamsGroupToolPolicy(
158
162
 
159
163
  const channelCandidates = buildChannelKeyCandidates(
160
164
  groupId,
161
- groupChannel,
162
- groupChannel ? normalizeChannelSlug(groupChannel) : undefined,
165
+ allowNameMatching ? groupChannel : undefined,
166
+ allowNameMatching && groupChannel ? normalizeChannelSlug(groupChannel) : undefined,
163
167
  );
164
168
  for (const teamConfig of Object.values(cfg.teams ?? {})) {
165
169
  const match = resolveChannelEntryMatchWithFallback({