fix(matrix): trust m.mentions.user_ids as authoritative mention source

resolveMentions() required BOTH m.mentions.user_ids metadata AND a
visible text or formatted_body mention for a user mention to register.
When non-OpenClaw Matrix clients (Element, standalone bots via
matrix-bot-sdk) send proper m.mentions metadata without duplicating
the @-mention in the message body, the mention was silently ignored
and requireMention: true dropped the message.

Per MSC3952, m.mentions.user_ids is the authoritative mention source.
The visible @-mention in the body is a display hint, not a
prerequisite. Drop the conjunction so metadata-backed mentions are
trusted on their own.

The m.mentions.room check is left unchanged — visible @room text is
still required alongside the metadata flag because @room mentions
have different security implications (spam amplification).

Fixes #64785
This commit is contained in:
hclsys
2026-04-11 20:18:08 +08:00
committed by Gustavo Madeira Santana
parent d69ab71c87
commit 9be1e95dab
2 changed files with 14 additions and 8 deletions

View File

@@ -34,19 +34,22 @@ describe("resolveMentions", () => {
expect(result.hasExplicitMention).toBe(true);
});
it("does not trust forged m.mentions.user_ids without a visible mention", () => {
it("detects mention via m.mentions.user_ids even without visible text mention (#64785)", () => {
// MSC3952: m.mentions.user_ids is the authoritative mention source.
// Non-OpenClaw Matrix clients (Element, standalone bots) may set
// m.mentions without including @bot in the visible message body.
const result = resolveMentions({
content: {
msgtype: "m.text",
body: "hello",
body: "please reply",
"m.mentions": { user_ids: ["@bot:matrix.org"] },
},
userId,
text: "hello",
text: "please reply",
mentionRegexes,
});
expect(result.wasMentioned).toBe(false);
expect(result.hasExplicitMention).toBe(false);
expect(result.wasMentioned).toBe(true);
expect(result.hasExplicitMention).toBe(true);
});
it("detects room mention via visible @room text", () => {

View File

@@ -163,10 +163,13 @@ export function resolveMentions(params: {
mentionRegexes: params.mentionRegexes,
})
: false;
// m.mentions.user_ids is the authoritative mention source per MSC3952.
// Previously this also required a visible text or formatted_body mention,
// which caused messages from non-OpenClaw clients that send proper
// m.mentions metadata without an @-mention in the body to be silently
// ignored when requireMention was enabled (#64785).
const metadataBackedUserMention = Boolean(
params.userId &&
mentionedUsers.has(params.userId) &&
(mentionedInFormattedBody || textMentioned),
params.userId && mentionedUsers.has(params.userId),
);
const metadataBackedRoomMention = Boolean(mentions?.room) && visibleRoomMention;
const explicitMention =