Skip to content
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions apps/meteor/app/api/server/v1/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,22 @@ const chatEndpoints = API.v1
return API.v1.failure(`No message found with the id of "${bodyParams.msgId}".`);
}

// Reject modifications to soft-deleted messages
if (msg.t === 'rm') {
return API.v1.failure('Cannot edit a deleted message.');
}

// Sanitize invisible control characters to prevent empty message bypass
if ('text' in bodyParams && typeof bodyParams.text === 'string') {
const sanitizedText = bodyParams.text.replace(/[\p{Cc}]/gu, '').trim();
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Outdated

if (sanitizedText.length === 0) {
return API.v1.failure('Message cannot be empty or contain only invisible control characters.');
}

bodyParams.text = bodyParams.text.replace(/[\p{Cc}]/gu, '');
}

if (bodyParams.roomId !== msg.rid) {
return API.v1.failure('The room id provided does not match where the message is from.');
}
Expand Down Expand Up @@ -837,6 +853,19 @@ const chatEndpoints = API.v1
throw new Error("Cannot send system messages using 'chat.sendMessage'");
}

// Sanitize invisible control characters to prevent empty message bypass
const msgPayload = this.bodyParams.message as { msg?: string; attachments?: any[] };
if (msgPayload && typeof msgPayload.msg === 'string') {
const sanitizedMsg = msgPayload.msg.replace(/[\p{Cc}]/gu, '').trim();

// Reject if the message is empty and has no attachments
if (sanitizedMsg.length === 0 && (!msgPayload.attachments || msgPayload.attachments.length === 0)) {
return API.v1.failure('Message cannot be empty or contain only invisible control characters.');
}

msgPayload.msg = msgPayload.msg.replace(/[\p{Cc}]/gu, '');
}

const sent = await applyAirGappedRestrictionsValidation(() =>
executeSendMessage(this.user, this.bodyParams.message as Pick<IMessage, 'rid'>, { previewUrls: this.bodyParams.previewUrls }),
);
Expand Down