Skip to content

Commit

Permalink
fix: imported fixes (#33454)
Browse files Browse the repository at this point in the history
  • Loading branch information
julio-cfa authored Nov 1, 2024
1 parent 0233218 commit fbf4245
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changeset/funny-icons-develop.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)
48 changes: 46 additions & 2 deletions apps/meteor/app/otr/server/methods/updateOTRAck.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Rooms } from '@rocket.chat/models';
import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check, Match } from 'meteor/check';
import { Meteor } from 'meteor/meteor';

import { canAccessRoomAsync } from '../../../authorization/server';
import notifications from '../../../notifications/server/lib/Notifications';

declare module '@rocket.chat/ui-contexts' {
Expand All @@ -11,10 +14,51 @@ declare module '@rocket.chat/ui-contexts' {
}

Meteor.methods<ServerMethods>({
updateOTRAck({ message, ack }) {
if (!Meteor.userId()) {
async updateOTRAck({ message, ack }) {
const uid = Meteor.userId();

if (!uid) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'updateOTRAck' });
}

check(ack, String);
check(message, {
_id: String,
rid: String,
msg: String,
t: Match.Any,
ts: Date,
u: {
_id: String,
username: String,
name: String,
},
_updatedAt: Date,
urls: Match.Any,
mentions: Match.Any,
channels: Match.Optional([
{
_id: String,
name: String,
},
]),
otr: Match.Maybe({ ack: String }),
});

if (message?.t !== 'otr') {
throw new Meteor.Error('error-invalid-message', 'Invalid message type', { method: 'updateOTRAck' });
}

const room = await Rooms.findOneById(message.rid, { projection: { t: 1, _id: 1, uids: 1 } });

if (!room) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'updateOTRAck' });
}

if (!(await canAccessRoomAsync(room, { _id: uid })) || (room.uids && (!message.u._id || !room.uids.includes(message.u._id)))) {
throw new Meteor.Error('error-invalid-user', 'Invalid user, not in room', { method: 'updateOTRAck' });
}

const otrStreamer = notifications.streamRoomMessage;
otrStreamer.emit(message.rid, { ...message, otr: { ack } });
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { Box, Callout, Chip, Margins } from '@rocket.chat/fuselage';
import { ExternalLink } from '@rocket.chat/ui-client';
import type { TranslationKey } from '@rocket.chat/ui-contexts';
import { useTranslation } from '@rocket.chat/ui-contexts';
import DOMPurify from 'dompurify';
import React from 'react';

import ScreenshotCarouselAnchor from '../../../components/ScreenshotCarouselAnchor';
import type { AppInfo } from '../../../definitions/AppInfo';
import { purifyOptions } from '../../../lib/purifyOptions';
import AppDetailsAPIs from './AppDetailsAPIs';
import { normalizeUrl } from './normalizeUrl';

Expand Down Expand Up @@ -61,7 +63,14 @@ const AppDetails = ({ app }: AppDetailsProps) => {
<Box fontScale='h4' mbe={8} color='titles-labels'>
{t('Description')}
</Box>
<Box dangerouslySetInnerHTML={{ __html: isMarkdown ? detailedDescription.rendered : description }} withRichContent />
<Box
dangerouslySetInnerHTML={{
__html: isMarkdown
? DOMPurify.sanitize(detailedDescription.rendered, purifyOptions)
: DOMPurify.sanitize(description, purifyOptions),
}}
withRichContent
/>
</Box>

<Box is='section'>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Accordion, Box } from '@rocket.chat/fuselage';
import { useTranslation } from '@rocket.chat/ui-contexts';
import DOMPurify from 'dompurify';
import type { ReactElement } from 'react';
import React from 'react';

import { useTimeAgo } from '../../../../../hooks/useTimeAgo';
import { purifyOptions } from '../../../lib/purifyOptions';

type IRelease = {
version: string;
Expand Down Expand Up @@ -36,7 +38,7 @@ const AppReleasesItem = ({ release, ...props }: ReleaseItemProps): ReactElement
return (
<Accordion.Item title={title} {...props}>
{release.detailedChangelog?.rendered ? (
<Box dangerouslySetInnerHTML={{ __html: release.detailedChangelog?.rendered }} color='default' />
<Box dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(release.detailedChangelog?.rendered, purifyOptions) }} color='default' />
) : (
<Box color='default'>{t('No_release_information_provided')}</Box>
)}
Expand Down
50 changes: 50 additions & 0 deletions apps/meteor/client/views/marketplace/lib/purifyOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
export const purifyOptions = {
ALLOWED_TAGS: [
'b',
'i',
'em',
'strong',
'br',
'p',
'ul',
'ol',
'li',
'article',
'aside',
'figure',
'section',
'summary',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'hgroup',
'div',
'hr',
'span',
'wbr',
'abbr',
'acronym',
'cite',
'code',
'dfn',
'figcaption',
'mark',
's',
'samp',
'sub',
'sup',
'var',
'time',
'q',
'del',
'ins',
'rp',
'rt',
'ruby',
'bdi',
'bdo',
],
};
3 changes: 3 additions & 0 deletions packages/core-typings/src/IMessage/IMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ export interface IMessage extends IRocketChatRecord {
t?: MessageTypesValues;
e2e?: 'pending' | 'done';
otrAck?: string;
otr?: {
ack: string;
};

urls?: MessageUrl[];

Expand Down
2 changes: 2 additions & 0 deletions packages/gazzodown/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
"react": "*"
},
"dependencies": {
"@types/dompurify": "^3.0.5",
"dompurify": "^3.1.7",
"highlight.js": "^11.5.1",
"react-error-boundary": "^3.1.4"
},
Expand Down
10 changes: 6 additions & 4 deletions packages/gazzodown/src/emoji/EmojiRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { MessageEmoji, ThreadMessageEmoji } from '@rocket.chat/fuselage';
import type * as MessageParser from '@rocket.chat/message-parser';
import DOMPurify from 'dompurify';
import { ReactElement, useMemo, useContext, memo } from 'react';

import { MarkupInteractionContext } from '../MarkupInteractionContext';
Expand All @@ -13,11 +14,12 @@ const EmojiRenderer = ({ big = false, preview = false, ...emoji }: EmojiProps):
const { detectEmoji } = useContext(MarkupInteractionContext);

const fallback = useMemo(() => ('unicode' in emoji ? emoji.unicode : `:${emoji.shortCode ?? emoji.value.value}:`), [emoji]);
const sanitizedFallback = DOMPurify.sanitize(fallback);

const descriptors = useMemo(() => {
const detected = detectEmoji?.(fallback);
const detected = detectEmoji?.(sanitizedFallback);
return detected?.length !== 0 ? detected : undefined;
}, [detectEmoji, fallback]);
}, [detectEmoji, sanitizedFallback]);

return (
<>
Expand All @@ -34,8 +36,8 @@ const EmojiRenderer = ({ big = false, preview = false, ...emoji }: EmojiProps):
)}
</span>
)) ?? (
<span role='img' aria-label={fallback.charAt(0) === ':' ? fallback : undefined}>
{fallback}
<span role='img' aria-label={sanitizedFallback.charAt(0) === ':' ? sanitizedFallback : undefined}>
{sanitizedFallback}
</span>
)}
</>
Expand Down

0 comments on commit fbf4245

Please sign in to comment.