Update README and configuration to replace RSA with Ed25519 for federation security
All checks were successful
Build & Push Docker Image / build (push) Successful in 6m30s

This commit is contained in:
2026-02-28 20:19:59 +01:00
parent 2831f80ab4
commit c281628fdc
8 changed files with 74 additions and 34 deletions

View File

@@ -172,6 +172,13 @@ router.post('/', authenticateToken, async (req, res) => {
if (moderator_code && moderator_code.length > 50) {
return res.status(400).json({ error: 'Moderator code must not exceed 50 characters' });
}
// S2: validate max_participants as non-negative integer
if (max_participants !== undefined && max_participants !== null) {
const mp = Number(max_participants);
if (!Number.isInteger(mp) || mp < 0 || mp > 10000) {
return res.status(400).json({ error: 'max_participants must be a non-negative integer (max 10000)' });
}
}
const uid = crypto.randomBytes(8).toString('hex');
const db = getDb();
@@ -240,6 +247,13 @@ router.put('/:uid', authenticateToken, async (req, res) => {
if (moderator_code && moderator_code.length > 50) {
return res.status(400).json({ error: 'Moderator code must not exceed 50 characters' });
}
// S2: validate max_participants on update
if (max_participants !== undefined && max_participants !== null) {
const mp = Number(max_participants);
if (!Number.isInteger(mp) || mp < 0 || mp > 10000) {
return res.status(400).json({ error: 'max_participants must be a non-negative integer (max 10000)' });
}
}
await db.run(`
UPDATE rooms SET
@@ -641,8 +655,9 @@ router.post('/:uid/presentation', authenticateToken, async (req, res) => {
// Remove old presentation file if exists
if (room.presentation_file) {
const oldPath = path.join(presentationsDir, room.presentation_file);
if (fs.existsSync(oldPath)) fs.unlinkSync(oldPath);
// S8: defense-in-depth path traversal check
const oldPath = path.resolve(presentationsDir, room.presentation_file);
if (oldPath.startsWith(presentationsDir + path.sep) && fs.existsSync(oldPath)) fs.unlinkSync(oldPath);
}
fs.writeFileSync(filepath, buffer);
@@ -663,8 +678,9 @@ router.delete('/:uid/presentation', authenticateToken, async (req, res) => {
if (!room) return res.status(404).json({ error: 'Room not found or no permission' });
if (room.presentation_file) {
const filepath = path.join(presentationsDir, room.presentation_file);
if (fs.existsSync(filepath)) fs.unlinkSync(filepath);
// S8: defense-in-depth path traversal check
const filepath = path.resolve(presentationsDir, room.presentation_file);
if (filepath.startsWith(presentationsDir + path.sep) && fs.existsSync(filepath)) fs.unlinkSync(filepath);
}
await db.run('UPDATE rooms SET presentation_file = NULL, presentation_name = NULL, updated_at = CURRENT_TIMESTAMP WHERE uid = ?', [req.params.uid]);