Skip to content

Commit 52eb8a9

Browse files
twassmandbkr
andauthored
Strip mentions from forwarded messages (#30884)
* strip mentions from forwarded messages fixes #30883 * call attachMentions() for empty m.mentions in forwarded messages As there is no EditorModel, attachMentions() currently does nothing * fix lint and typecheck * update test "should be navigable using arrow keys" * update test "forwards pin drop event" add empty mentions to expected content * add doc to transformEvent() & elaborate on attachMentions() * add test "strips mentions from forwarded messages" * fix lint * update source of `attachMentions()` import --------- Co-authored-by: David Baker <[email protected]>
1 parent c4ef57b commit 52eb8a9

File tree

2 files changed

+61
-9
lines changed

2 files changed

+61
-9
lines changed

src/components/views/dialogs/ForwardDialog.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import {
5757
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
5858
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
5959
import { OverflowTileView } from "../rooms/OverflowTileView";
60+
import { attachMentions } from "../../../utils/messages";
6061

6162
const AVATAR_SIZE = 30;
6263

@@ -178,7 +179,18 @@ const Entry: React.FC<IEntryProps<any>> = ({ room, type, content, matrixClient:
178179
);
179180
};
180181

181-
const transformEvent = (event: MatrixEvent): { type: string; content: IContent } => {
182+
/**
183+
* Transform content of a MatrixEvent before forwarding:
184+
* 1. Strip all relations.
185+
* 2. Convert location events into a static pin-drop location share,
186+
* and remove description from self-location shares.
187+
* 3. Pass through attachMentions() to strip mentions (as no EditorModel is present to recalculate from).
188+
*
189+
* @param event - The MatrixEvent to transform.
190+
* @param userId - Current user MXID (passed through to attachMentions()).
191+
* @returns The transformed event type and content.
192+
*/
193+
const transformEvent = (event: MatrixEvent, userId: string): { type: string; content: IContent } => {
182194
const {
183195
// eslint-disable-next-line @typescript-eslint/no-unused-vars
184196
"m.relates_to": _, // strip relations - in future we will attach a relation pointing at the original event
@@ -213,6 +225,13 @@ const transformEvent = (event: MatrixEvent): { type: string; content: IContent }
213225
};
214226
}
215227

228+
// Mentions can leak information about the context of the original message,
229+
// so pass through attachMentions() to recalculate mentions.
230+
// Currently, this strips all mentions (forces an empty m.mentions),
231+
// as there is no EditorModel to parse pills from.
232+
// Future improvements could actually recalculate mentions based on the message body.
233+
attachMentions(userId, content, null, undefined);
234+
216235
return { type, content };
217236
};
218237

@@ -223,7 +242,7 @@ const ForwardDialog: React.FC<IProps> = ({ matrixClient: cli, event, permalinkCr
223242
cli.getProfileInfo(userId).then((info) => setProfileInfo(info));
224243
}, [cli, userId]);
225244

226-
const { type, content } = transformEvent(event);
245+
const { type, content } = transformEvent(event, userId);
227246

228247
// For the message preview we fake the sender as ourselves
229248
const mockEvent = new MatrixEvent({

test/unit-tests/components/views/dialogs/ForwardDialog-test.tsx

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,9 @@ describe("ForwardDialog", () => {
153153

154154
await userEvent.keyboard("[Enter]");
155155
expect(mockClient.sendEvent).toHaveBeenCalledWith("A", "m.room.message", {
156-
body: "Hello world!",
157-
msgtype: "m.text",
156+
"body": "Hello world!",
157+
"msgtype": "m.text",
158+
"m.mentions": {},
158159
});
159160
});
160161

@@ -248,6 +249,37 @@ describe("ForwardDialog", () => {
248249
expect(secondButton.getAttribute("aria-disabled")).toBeFalsy();
249250
});
250251

252+
it("strips mentions from forwarded messages", async () => {
253+
const messageWithMention = mkEvent({
254+
type: "m.room.message",
255+
room: sourceRoom,
256+
user: "@bob:example.org",
257+
content: {
258+
"msgtype": "m.text",
259+
"body": "Hi @alice:example.org",
260+
"m.mentions": {
261+
user_ids: ["@alice:example.org"],
262+
},
263+
},
264+
event: true,
265+
});
266+
267+
const { container } = mountForwardDialog(messageWithMention);
268+
const roomId = "a";
269+
270+
// Click the send button.
271+
act(() => {
272+
const sendButton = container.querySelector(".mx_ForwardList_sendButton");
273+
fireEvent.click(sendButton!);
274+
});
275+
276+
// Expected content should have mentions empty.
277+
expect(mockClient.sendEvent).toHaveBeenCalledWith(roomId, messageWithMention.getType(), {
278+
...messageWithMention.getContent(),
279+
"m.mentions": {},
280+
});
281+
});
282+
251283
describe("Location events", () => {
252284
// 14.03.2022 16:15
253285
const now = 1647270879403;
@@ -357,11 +389,12 @@ describe("ForwardDialog", () => {
357389

358390
sendToFirstRoom(container);
359391

360-
expect(mockClient.sendEvent).toHaveBeenCalledWith(
361-
roomId,
362-
pinDropLocationEvent.getType(),
363-
pinDropLocationEvent.getContent(),
364-
);
392+
const expectedContent = {
393+
...pinDropLocationEvent.getContent(),
394+
"m.mentions": {}, // Add mentions (explicitly set to empty)
395+
};
396+
397+
expect(mockClient.sendEvent).toHaveBeenCalledWith(roomId, pinDropLocationEvent.getType(), expectedContent);
365398
});
366399
});
367400

0 commit comments

Comments
 (0)