Enhance security and validation across multiple routes:
All checks were successful
Build & Push Docker Image / build (push) Successful in 6m25s

- Escape XML and HTML special characters to prevent injection attacks.
- Implement rate limiting for various endpoints to mitigate abuse.
- Add validation for email formats, password lengths, and field limits.
- Ensure proper access control for recordings and room management.
This commit is contained in:
2026-02-28 19:49:29 +01:00
parent 616442a82a
commit 7466f3513d
10 changed files with 398 additions and 47 deletions

View File

@@ -2,6 +2,17 @@ import nodemailer from 'nodemailer';
let transporter;
// Escape HTML special characters to prevent injection in email bodies
function escapeHtml(str) {
if (!str) return '';
return String(str)
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
export function initMailer() {
const host = process.env.SMTP_HOST;
const port = parseInt(process.env.SMTP_PORT || '587', 10);
@@ -44,6 +55,8 @@ export async function sendVerificationEmail(to, name, verifyUrl, appName = 'Redl
}
const from = process.env.SMTP_FROM || process.env.SMTP_USER;
const safeName = escapeHtml(name);
const safeAppName = escapeHtml(appName);
await transporter.sendMail({
from: `"${appName}" <${from}>`,
@@ -51,7 +64,7 @@ export async function sendVerificationEmail(to, name, verifyUrl, appName = 'Redl
subject: `${appName} Verify your email`,
html: `
<div style="font-family:Arial,sans-serif;max-width:520px;margin:0 auto;padding:32px;background:#1e1e2e;color:#cdd6f4;border-radius:12px;">
<h2 style="color:#cba6f7;margin-top:0;">Hey ${name} 👋</h2>
<h2 style="color:#cba6f7;margin-top:0;">Hey ${safeName} 👋</h2>
<p>Please verify your email address by clicking the button below:</p>
<p style="text-align:center;margin:28px 0;">
<a href="${verifyUrl}"
@@ -61,7 +74,7 @@ export async function sendVerificationEmail(to, name, verifyUrl, appName = 'Redl
</p>
<p style="font-size:13px;color:#7f849c;">
Or copy this link in your browser:<br/>
<a href="${verifyUrl}" style="color:#89b4fa;word-break:break-all;">${verifyUrl}</a>
<a href="${verifyUrl}" style="color:#89b4fa;word-break:break-all;">${escapeHtml(verifyUrl)}</a>
</p>
<p style="font-size:13px;color:#7f849c;">This link is valid for 24 hours.</p>
<hr style="border:none;border-top:1px solid #313244;margin:24px 0;"/>
@@ -86,6 +99,11 @@ export async function sendFederationInviteEmail(to, name, fromUser, roomName, me
if (!transporter) return; // silently skip if SMTP not configured
const from = process.env.SMTP_FROM || process.env.SMTP_USER;
const safeName = escapeHtml(name);
const safeFromUser = escapeHtml(fromUser);
const safeRoomName = escapeHtml(roomName);
const safeMessage = message ? escapeHtml(message) : null;
const safeAppName = escapeHtml(appName);
await transporter.sendMail({
from: `"${appName}" <${from}>`,
@@ -93,12 +111,12 @@ export async function sendFederationInviteEmail(to, name, fromUser, roomName, me
subject: `${appName} Meeting invitation from ${fromUser}`,
html: `
<div style="font-family:Arial,sans-serif;max-width:520px;margin:0 auto;padding:32px;background:#1e1e2e;color:#cdd6f4;border-radius:12px;">
<h2 style="color:#cba6f7;margin-top:0;">Hey ${name} 👋</h2>
<p>You have received a meeting invitation from <strong style="color:#cdd6f4;">${fromUser}</strong>.</p>
<h2 style="color:#cba6f7;margin-top:0;">Hey ${safeName} 👋</h2>
<p>You have received a meeting invitation from <strong style="color:#cdd6f4;">${safeFromUser}</strong>.</p>
<div style="background:#313244;border-radius:8px;padding:16px;margin:20px 0;">
<p style="margin:0 0 8px 0;font-size:13px;color:#7f849c;">Room:</p>
<p style="margin:0;font-size:16px;font-weight:bold;color:#cdd6f4;">${roomName}</p>
${message ? `<p style="margin:12px 0 0 0;font-size:13px;color:#a6adc8;font-style:italic;">"${message}"</p>` : ''}
<p style="margin:0;font-size:16px;font-weight:bold;color:#cdd6f4;">${safeRoomName}</p>
${safeMessage ? `<p style="margin:12px 0 0 0;font-size:13px;color:#a6adc8;font-style:italic;">&quot;${safeMessage}&quot;</p>` : ''}
</div>
<p style="text-align:center;margin:28px 0;">
<a href="${inboxUrl}"