Enhance security and validation across multiple routes:
All checks were successful
Build & Push Docker Image / build (push) Successful in 6m25s
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:
@@ -11,6 +11,13 @@ const __dirname = path.dirname(__filename);
|
||||
|
||||
const router = Router();
|
||||
|
||||
// Allowlist of valid theme IDs (keep in sync with src/themes/index.js)
|
||||
const VALID_THEMES = new Set([
|
||||
'light', 'dark', 'dracula', 'mocha', 'latte', 'nord', 'tokyo-night',
|
||||
'gruvbox-dark', 'gruvbox-light', 'rose-pine', 'rose-pine-dawn',
|
||||
'solarized-dark', 'solarized-light', 'one-dark', 'github-dark', 'scrunkly-cat',
|
||||
]);
|
||||
|
||||
// Ensure uploads/branding directory exists
|
||||
const brandingDir = path.join(__dirname, '..', '..', 'uploads', 'branding');
|
||||
if (!fs.existsSync(brandingDir)) {
|
||||
@@ -97,6 +104,15 @@ router.get('/logo', (req, res) => {
|
||||
if (!logoFile) {
|
||||
return res.status(404).json({ error: 'No logo found' });
|
||||
}
|
||||
// H5: serve SVG as attachment (Content-Disposition) to prevent in-browser script execution.
|
||||
// For non-SVG images, inline display is fine.
|
||||
const ext = path.extname(logoFile).toLowerCase();
|
||||
if (ext === '.svg') {
|
||||
res.setHeader('Content-Type', 'image/svg+xml');
|
||||
res.setHeader('Content-Disposition', 'attachment; filename="logo.svg"');
|
||||
res.setHeader('X-Content-Type-Options', 'nosniff');
|
||||
return res.sendFile(logoFile);
|
||||
}
|
||||
res.sendFile(logoFile);
|
||||
});
|
||||
|
||||
@@ -150,6 +166,9 @@ router.put('/name', authenticateToken, requireAdmin, async (req, res) => {
|
||||
if (!appName || !appName.trim()) {
|
||||
return res.status(400).json({ error: 'App name is required' });
|
||||
}
|
||||
if (appName.trim().length > 100) {
|
||||
return res.status(400).json({ error: 'App name must not exceed 100 characters' });
|
||||
}
|
||||
await setSetting('app_name', appName.trim());
|
||||
res.json({ appName: appName.trim() });
|
||||
} catch (err) {
|
||||
@@ -165,6 +184,10 @@ router.put('/default-theme', authenticateToken, requireAdmin, async (req, res) =
|
||||
if (!defaultTheme || !defaultTheme.trim()) {
|
||||
return res.status(400).json({ error: 'defaultTheme is required' });
|
||||
}
|
||||
// H4: validate against known theme IDs
|
||||
if (!VALID_THEMES.has(defaultTheme.trim())) {
|
||||
return res.status(400).json({ error: 'Invalid theme' });
|
||||
}
|
||||
await setSetting('default_theme', defaultTheme.trim());
|
||||
res.json({ defaultTheme: defaultTheme.trim() });
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user