VYPR
High severity7.5NVD Advisory· Published May 28, 2026

CVE-2026-32995

CVE-2026-32995

Description

The Rocket.Chat DDP method autoTranslate.translateMessage in versions <8.5.0, <8.4.2, <8.3.4, <8.2.4, <8.1.5, <8.0.5, <7.13.8, and <7.10.12 accepts a client-supplied IMessage object and passes it directly to translateMessage() without checking Meteor.userId() or verifying room membership. Any authenticated DDP user can read the content of any message by ID from any room (private channels, DMs, E2EE rooms) by calling this method.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Authenticated DDP users can read any room's messages by ID via the autoTranslate.translateMessage method in Rocket.Chat before patched versions.

Vulnerability

The Rocket.Chat DDP method autoTranslate.translateMessage in versions <8.5.0, <8.4.2, <8.3.4, <8.2.4, <8.1.5, <8.0.5, <7.13.8, and <7.10.12 accepts a client-supplied IMessage object and passes it directly to translateMessage() without checking Meteor.userId() or verifying room membership. This allows any authenticated DDP user to read the content of any message by ID, including messages from private channels, direct messages, and end-to-end encrypted rooms.

Exploitation

An attacker only needs a valid authenticated DDP session. By calling the autoTranslate.translateMessage method with a target message ID, they can retrieve the message content without belonging to the room or having any special privileges. No user interaction is required.

Impact

Successful exploitation leads to unauthorized disclosure of message content across all rooms, including private channels, DMs, and E2EE rooms. The attacker gains read access to sensitive information, bypassing room membership and encryption controls.

Mitigation

The vulnerability is fixed in pull request #40528 [1]. Administrators should upgrade to Rocket.Chat versions 8.5.0, 8.4.2, 8.3.4, 8.2.4, 8.1.5, 8.0.5, 7.13.8, or 7.10.12 or later. No workarounds are documented.

AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2
  • RocketChat/Rocket.chatreferences2 versions
    (expand)+ 1 more
    • (no CPE)
    • (no CPE)range: <8.5.0, <8.4.2, <8.3.4, <8.2.4, <8.1.5, <8.0.5, <7.13.8, <7.10.12

Patches

1
5c8efa79ece3

fix: ensures the translateMessage Meteor method validates access and type (#40528)

https://github.com/rocketchat/rocket.chatJulio AraujoMay 14, 2026via nvd-ref
3 files changed · +114 2
  • apps/meteor/app/autotranslate/server/methods/translateMessage.ts+20 1 modified
    @@ -1,7 +1,10 @@
     import type { IMessage } from '@rocket.chat/core-typings';
     import type { ServerMethods } from '@rocket.chat/ddp-client';
    +import { Messages, Rooms } from '@rocket.chat/models';
    +import { check } from 'meteor/check';
     import { Meteor } from 'meteor/meteor';
     
    +import { canAccessRoomAsync } from '../../../authorization/server';
     import { translateMessage } from '../functions/translateMessage';
     
     declare module '@rocket.chat/ddp-client' {
    @@ -13,6 +16,22 @@ declare module '@rocket.chat/ddp-client' {
     
     Meteor.methods<ServerMethods>({
     	async 'autoTranslate.translateMessage'(message, targetLanguage) {
    -		return translateMessage(targetLanguage, message);
    +		const userId = Meteor.userId();
    +		if (!userId) {
    +			throw new Meteor.Error('error-invalid-user', 'Invalid user', {
    +				method: 'autoTranslate.translateMessage',
    +			});
    +		}
    +		check(message?._id, String);
    +		check(targetLanguage, String);
    +		const msg = await Messages.findOneById(message._id);
    +		if (!msg) {
    +			throw new Meteor.Error('error-message-not-found', 'Message not found');
    +		}
    +		const room = await Rooms.findOneById(msg.rid);
    +		if (!room || !(await canAccessRoomAsync(room, { _id: userId }))) {
    +			throw new Meteor.Error('error-not-allowed', 'Not allowed');
    +		}
    +		return translateMessage(targetLanguage, msg);
     	},
     });
    
  • apps/meteor/tests/end-to-end/api/autotranslate.ts+89 1 modified
    @@ -3,7 +3,7 @@ import type { IMessage, IRoom, IUser } from '@rocket.chat/core-typings';
     import { expect } from 'chai';
     import { before, describe, after, it } from 'mocha';
     
    -import { getCredentials, api, request, credentials } from '../../data/api-data';
    +import { getCredentials, api, request, credentials, methodCall } from '../../data/api-data';
     import { sendSimpleMessage } from '../../data/chat.helper';
     import { updatePermission, updateSetting } from '../../data/permissions.helper';
     import { createRoom, deleteRoom } from '../../data/rooms.helper';
    @@ -434,6 +434,94 @@ describe('AutoTranslate', () => {
     			});
     		});
     
    +		describe('[autoTranslate.translateMessage method]', () => {
    +			let userA: TestUser<IUser>;
    +			let userB: TestUser<IUser>;
    +			let credA: Credentials;
    +			let credB: Credentials;
    +			let privateRoom: IRoom;
    +			let privateMessage: IMessage;
    +
    +			before(async () => {
    +				await updateSetting('AutoTranslate_Enabled', true);
    +
    +				userA = await createUser();
    +				userB = await createUser();
    +
    +				credA = await login(userA.username, password);
    +				credB = await login(userB.username, password);
    +
    +				privateRoom = (
    +					await createRoom({
    +						type: 'p',
    +						name: `test-autotranslate-method-${Date.now()}`,
    +						credentials: credA,
    +					})
    +				).body.group;
    +
    +				const msgRes = await sendSimpleMessage({
    +					roomId: privateRoom._id,
    +					text: 'Isso é um teste',
    +					userCredentials: credA,
    +				});
    +				privateMessage = msgRes.body.message;
    +			});
    +
    +			after(async () => {
    +				await Promise.all([
    +					updateSetting('AutoTranslate_Enabled', false),
    +					deleteUser(userA),
    +					deleteUser(userB),
    +					deleteRoom({ type: 'p', roomId: privateRoom._id }),
    +				]);
    +			});
    +
    +			it('should fail when messageId is not a string', (done) => {
    +				void request
    +					.post(methodCall('autoTranslate.translateMessage'))
    +					.set(credA)
    +					.send({
    +						message: JSON.stringify({
    +							msg: 'method',
    +							id: 'id',
    +							method: 'autoTranslate.translateMessage',
    +							params: [{ _id: { $gt: '' } }, 'en'],
    +						}),
    +					})
    +					.expect('Content-Type', 'application/json')
    +					.expect(400)
    +					.expect((res) => {
    +						expect(res.body).to.have.a.property('success', false);
    +						const parsedBody = JSON.parse(res.body.message);
    +						expect(parsedBody).to.have.a.property('error');
    +					})
    +					.end(done);
    +			});
    +
    +			it('should return error-not-allowed when the caller is not a member of the room', (done) => {
    +				void request
    +					.post(methodCall('autoTranslate.translateMessage'))
    +					.set(credB)
    +					.send({
    +						message: JSON.stringify({
    +							msg: 'method',
    +							id: 'id',
    +							method: 'autoTranslate.translateMessage',
    +							params: [{ _id: privateMessage._id }, 'en'],
    +						}),
    +					})
    +					.expect('Content-Type', 'application/json')
    +					.expect(400)
    +					.expect((res) => {
    +						expect(res.body).to.have.a.property('success', false);
    +						const parsedBody = JSON.parse(res.body.message);
    +						expect(parsedBody).to.have.a.property('error');
    +						expect(parsedBody.error).to.have.a.property('error', 'error-not-allowed');
    +					})
    +					.end(done);
    +			});
    +		});
    +
     		describe('Autoenable setting', () => {
     			let userA: TestUser<IUser>;
     			let userB: TestUser<IUser>;
    
  • .changeset/neat-trams-juggle.md+5 0 added
    @@ -0,0 +1,5 @@
    +---
    +'@rocket.chat/meteor': patch
    +---
    +
    +Ensures the Meteor method for translateMessage validates access and types
    

Vulnerability mechanics

Root cause

"Missing authentication and authorization checks in the autoTranslate.translateMessage DDP method allow any authenticated user to read any message by ID."

Attack vector

An authenticated DDP user calls the Meteor method `autoTranslate.translateMessage` with a client-supplied `IMessage` object containing any message `_id`. The server previously accepted this without checking `Meteor.userId()` or verifying room membership [patch_id=2852673]. This allows any authenticated user to read the content of any message by ID, including messages from private channels, direct messages, and E2EE rooms, by simply providing the target message's `_id` and a language code.

Affected code

The vulnerable method is `autoTranslate.translateMessage` in `apps/meteor/app/autotranslate/server/methods/translateMessage.ts`. The original code directly called `translateMessage(targetLanguage, message)` without any access control or type validation [patch_id=2852673].

What the fix does

The patch adds three critical checks before calling `translateMessage()`. First, it validates that the caller is authenticated via `Meteor.userId()`. Second, it uses `check(message?._id, String)` to ensure the message ID is a string, preventing type-based injection. Third, it fetches the message and its room, then calls `canAccessRoomAsync()` to verify the caller is a member of that room. If any check fails, an appropriate Meteor.Error is thrown [patch_id=2852673].

Preconditions

  • authAttacker must be an authenticated DDP user on the Rocket.Chat server
  • inputAttacker must know or guess the _id of the target message

Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.