Skip to content

Commit

Permalink
fix: imported fixes (RocketChat#33330)
Browse files Browse the repository at this point in the history
  • Loading branch information
julio-cfa authored Sep 23, 2024
1 parent 9bcb802 commit 827850d
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/little-bottles-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates)
9 changes: 7 additions & 2 deletions apps/meteor/app/api/server/v1/rooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
findRoomsAvailableForTeams,
} from '../lib/rooms';

async function findRoomByIdOrName({
export async function findRoomByIdOrName({
params,
checkedArchived = true,
}: {
Expand Down Expand Up @@ -365,7 +365,12 @@ API.v1.addRoute(
{ authRequired: true, validateParams: isRoomsCleanHistoryProps },
{
async post() {
const { _id } = await findRoomByIdOrName({ params: this.bodyParams });
const room = await findRoomByIdOrName({ params: this.bodyParams });
const { _id } = room;

if (!room || !(await canAccessRoomAsync(room, { _id: this.userId }))) {
return API.v1.failure('User does not have access to the room [error-not-allowed]', 'error-not-allowed');
}

const {
latest,
Expand Down
8 changes: 8 additions & 0 deletions apps/meteor/app/lib/server/methods/cleanRoomHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';

import { findRoomByIdOrName } from '../../../api/server/v1/rooms';
import { canAccessRoomAsync } from '../../../authorization/server';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { cleanRoomHistory } from '../functions/cleanRoomHistory';

Expand Down Expand Up @@ -56,6 +58,12 @@ Meteor.methods<ServerMethods>({
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'cleanRoomHistory' });
}

const room = await findRoomByIdOrName({ params: { roomId } });

if (!room || !(await canAccessRoomAsync(room, { _id: userId }))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'cleanRoomHistory' });
}

return cleanRoomHistory({
rid: roomId,
latest,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { Box } from '@rocket.chat/fuselage';
import DOMPurify from 'dompurify';
import type { ReactElement } from 'react';
import React from 'react';

import OEmbedCollapsible from './OEmbedCollapsible';
import type { OEmbedPreviewMetadata } from './OEmbedPreviewMetadata';

const purifyOptions = {
ADD_TAGS: ['iframe'],
ADD_ATTR: ['frameborder', 'allow', 'allowfullscreen', 'scrolling', 'src', 'style', 'referrerpolicy'],
ALLOW_UNKNOWN_PROTOCOLS: true,
};

const OEmbedHtmlPreview = ({ html, ...props }: OEmbedPreviewMetadata): ReactElement => (
<OEmbedCollapsible {...props}>{html && <Box withRichContent dangerouslySetInnerHTML={{ __html: html }} />}</OEmbedCollapsible>
<OEmbedCollapsible {...props}>
{html && <Box withRichContent dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(html, purifyOptions) }} />}
</OEmbedCollapsible>
);

export default OEmbedHtmlPreview;
43 changes: 41 additions & 2 deletions apps/meteor/tests/end-to-end/api/methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -616,9 +616,19 @@ describe('Meteor.methods', () => {

describe('[@cleanRoomHistory]', () => {
let rid: IRoom['_id'];

let testUser: IUser;
let testUserCredentials: Credentials;
let channelName: string;

before('update permissions', async () => {
await updatePermission('clean-channel-history', ['admin', 'user']);
});

before('create test user', async () => {
testUser = await createUser();
testUserCredentials = await login(testUser.username, password);
});

before('create room', (done) => {
channelName = `methods-test-channel-${Date.now()}`;
void request
Expand Down Expand Up @@ -676,7 +686,36 @@ describe('Meteor.methods', () => {
.end(done);
});

after(() => deleteRoom({ type: 'p', roomId: rid }));
after(() =>
Promise.all([deleteRoom({ type: 'p', roomId: rid }), deleteUser(testUser), updatePermission('clean-channel-history', ['admin'])]),
);

it('should throw an error if user is not part of the room', async () => {
await request
.post(methodCall('cleanRoomHistory'))
.set(testUserCredentials)
.send({
message: JSON.stringify({
method: 'cleanRoomHistory',
params: [
{
roomId: rid,
oldest: { $date: new Date().getTime() },
latest: { $date: new Date().getTime() },
},
],
id: 'id',
msg: 'method',
}),
})
.expect(200)
.expect((res) => {
expect(res.body).to.have.a.property('success', true);
const data = JSON.parse(res.body.message);
expect(data).to.have.a.property('error').that.is.an('object');
expect(data.error).to.have.a.property('error', 'error-not-allowed');
});
});

it('should not change the _updatedAt value when nothing is changed on the room', async () => {
const roomBefore = await request.get(api('groups.info')).set(credentials).query({
Expand Down
28 changes: 28 additions & 0 deletions apps/meteor/tests/end-to-end/api/rooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,34 @@ describe('[Rooms]', () => {
})
.end(done);
});
describe('test user is not part of room', async () => {
beforeEach(async () => {
await updatePermission('clean-channel-history', ['admin', 'user']);
});

afterEach(async () => {
await updatePermission('clean-channel-history', ['admin']);
});

it('should return an error when the user with right privileges is not part of the room', async () => {
await request
.post(api('rooms.cleanHistory'))
.set(userCredentials)
.send({
roomId: privateChannel._id,
latest: '9999-12-31T23:59:59.000Z',
oldest: '0001-01-01T00:00:00.000Z',
limit: 2000,
})
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.property('errorType', 'error-not-allowed');
expect(res.body).to.have.property('error', 'User does not have access to the room [error-not-allowed]');
});
});
});
});
describe('[/rooms.info]', () => {
let testChannel: IRoom;
Expand Down

0 comments on commit 827850d

Please sign in to comment.