diff --git a/.changeset/olive-queens-protect.md b/.changeset/olive-queens-protect.md new file mode 100644 index 0000000000000..54251bde0b9f7 --- /dev/null +++ b/.changeset/olive-queens-protect.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +fix: Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) diff --git a/apps/meteor/server/publications/room/index.ts b/apps/meteor/server/publications/room/index.ts index dcb9c741f2376..5a457daa937e3 100644 --- a/apps/meteor/server/publications/room/index.ts +++ b/apps/meteor/server/publications/room/index.ts @@ -58,11 +58,15 @@ Meteor.methods({ } const userId = Meteor.userId(); - - if (!userId && settings.get('Accounts_AllowAnonymousRead') === false) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { - method: 'getRoomByTypeAndName', - }); + const isAnonymous = !userId; + + if (isAnonymous) { + const allowAnon = settings.get('Accounts_AllowAnonymousRead'); + if (!allowAnon || type !== 'c') { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { + method: 'getRoomByTypeAndName', + }); + } } const roomFind = roomCoordinator.getRoomFind(type); diff --git a/apps/meteor/tests/end-to-end/api/methods.ts b/apps/meteor/tests/end-to-end/api/methods.ts index 0d6651f74ba9b..6630be90104f7 100644 --- a/apps/meteor/tests/end-to-end/api/methods.ts +++ b/apps/meteor/tests/end-to-end/api/methods.ts @@ -2575,6 +2575,7 @@ describe('Meteor.methods', () => { let testUserCredentials: Credentials; let dmId: IRoom['_id']; let room: IRoom; + let privateRoom: IRoom; before(async () => { testUser = await createUser(); @@ -2613,14 +2614,49 @@ describe('Meteor.methods', () => { }); }); - after(() => - Promise.all([ + before(async () => { + privateRoom = ( + await createRoom({ + type: 'p', + name: `private.test.${Date.now()}-${Math.random()}`, + }) + ).body.group; + }); + + after(async () => { + await Promise.all([ deleteRoom({ type: 'd', roomId: dmId }), deleteRoom({ type: 'c', roomId: room._id }), + deleteRoom({ type: 'p', roomId: privateRoom._id }), deleteUser(testUser), deleteUser(testUser2), - ]), - ); + updateSetting('Accounts_AllowAnonymousRead', false), + ]); + }); + + it('should throw error when anonymous user tries to read private channel with anonymous read enabled', async () => { + await updateSetting('Accounts_AllowAnonymousRead', true); + + const payload = { + message: JSON.stringify({ + msg: 'method', + id: '2', + method: 'getRoomByTypeAndName', + params: ['p', privateRoom.name], + }), + }; + + const res = await request.post('/api/v1/method.callAnon/getRoomByTypeAndName').set('Content-Type', 'application/json').send(payload); + + expect(res.body).to.have.property('message'); + const parsedMessage = JSON.parse(res.body.message); + + expect(parsedMessage).to.have.property('error'); + expect(parsedMessage.error).to.have.property('error'); + expect(parsedMessage.error.error).to.equal('error-invalid-user'); + + await updateSetting('Accounts_AllowAnonymousRead', false); + }); it("should throw an error if the user isn't logged in", (done) => { void request