diff --git a/.changeset/fast-apes-know.md b/.changeset/fast-apes-know.md new file mode 100644 index 0000000000000..47242a936a4c2 --- /dev/null +++ b/.changeset/fast-apes-know.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Escapes HTML tags in exported data diff --git a/apps/meteor/server/lib/dataExport/exportRoomMessagesToFile.ts b/apps/meteor/server/lib/dataExport/exportRoomMessagesToFile.ts index 5b46c07d2e179..7649c32a5694a 100644 --- a/apps/meteor/server/lib/dataExport/exportRoomMessagesToFile.ts +++ b/apps/meteor/server/lib/dataExport/exportRoomMessagesToFile.ts @@ -2,6 +2,7 @@ import { mkdir, writeFile } from 'fs/promises'; import type { IMessage, IRoom, IUser, MessageAttachment, FileProp, RoomType, IExportOperation } from '@rocket.chat/core-typings'; import { Messages } from '@rocket.chat/models'; +import { escapeHTML } from '@rocket.chat/string-helpers'; import { settings } from '../../../app/settings/server'; import { readSecondaryPreferred } from '../../database/readSecondaryPreferred'; @@ -152,7 +153,7 @@ export const getMessageData = ( return messageObject; }; -export const exportMessageObject = (type: 'json' | 'html', messageObject: MessageData, messageFile?: FileProp): string => { +export const exportMessageObject = (type: 'json' | 'html', messageObject: MessageData, messageFiles: FileProp[] = []): string => { if (type === 'json') { return JSON.stringify(messageObject); } @@ -164,19 +165,22 @@ export const exportMessageObject = (type: 'json' | 'html', messageObject: Messag const italicTypes: IMessage['t'][] = ['uj', 'ul', 'au', 'r', 'ru', 'wm', 'livechat-close']; - const message = italicTypes.includes(messageType) ? `${messageObject.msg}` : messageObject.msg; + const safeMsg = escapeHTML(messageObject.msg ?? ''); + const message = italicTypes.includes(messageType) ? `${safeMsg}` : safeMsg; - file.push(`
${messageObject.username} (${timestamp}):
`);
+ file.push(`
${escapeHTML(messageObject.username ?? '')} (${timestamp}):
`);
file.push(message);
- if (messageFile?._id) {
- const attachment = messageObject.attachments?.find((att) => att.type === 'file' && att.title_link?.includes(messageFile._id));
+ for (const messageFile of messageFiles) {
+ if (messageFile?._id) {
+ const attachment = messageObject.attachments?.find((att) => att.type === 'file' && att.title_link?.includes(messageFile._id));
- const description = attachment?.title || i18n.t('Message_Attachments');
+ const description = attachment?.title || i18n.t('Message_Attachments');
- const assetUrl = `./assets/${messageFile._id}-${messageFile.name}`;
- const link = `
${description}`;
- file.push(link);
+ const assetUrl = `./assets/${messageFile._id}-${messageFile.name}`;
+ const link = `
${escapeHTML(description)}`;
+ file.push(link);
+ }
}
file.push('
${key}:`); + stream.write(`
${escapeHTML(key)}:`);
if (typeof value === 'string') {
- stream.write(value);
+ stream.write(escapeHTML(value));
} else if (Array.isArray(value)) {
stream.write('
');
for (const item of value) {
- stream.write(`${item}
`);
+ stream.write(`${escapeHTML(String(item))}
`);
}
}
diff --git a/apps/meteor/server/lib/dataExport/sendViaEmail.ts b/apps/meteor/server/lib/dataExport/sendViaEmail.ts
index dda337c851e44..834128a6a7f2a 100644
--- a/apps/meteor/server/lib/dataExport/sendViaEmail.ts
+++ b/apps/meteor/server/lib/dataExport/sendViaEmail.ts
@@ -1,5 +1,6 @@
import type { IMessage, IUser } from '@rocket.chat/core-typings';
import { Messages, Users } from '@rocket.chat/models';
+import { escapeHTML } from '@rocket.chat/string-helpers';
import moment from 'moment';
import * as Mailer from '../../../app/mailer/server/api';
@@ -67,9 +68,9 @@ export async function sendViaEmail(
)
.map((message: IMessage) => {
const dateTime = moment(message.ts).locale(lang).format('L LT');
- return `
${
- message.u.username
- } ${dateTime}
${Message.parse(message, data.language)}
${escapeHTML(
+ message.u.username ?? '',
+ )} ${dateTime}
${Message.parse(message, data.language)}