T05 · Unauthorized Access and Privilege Escalation
- Location
references/inboundEmail.js:103- Finding
Mailbox APIs Expose Sensitive Email Without Authentication
- Content
View full analysis
{ try { const limit = parseInt(req.query.limit) || 50; const files = fs.readdirSync(INBOX_DIR) .filter(f => f.endsWith('.json') && !f.includes('.processed') && f !== '.lastcheck') .sort().reverse().slice(0, limit); const emails = files.map(f => { try { return JSON.parse(fs.readFileSync(path.join(INBOX_DIR, f), 'utf8')); } catch { return null; } }).filter(Boolean); res.json({ emails, count: emails.length }); } catch (err) { res.status(500).json({ error: 'Failed to read inbox' }); } }); // GET /:id — Read specific email (marks as read) router.get('/:id', async (req, res) => { try { const filePath = path.join(INBOX_DIR, `${req.params.id}.json`); if (!fs.existsSync(filePath)) return res.status(404).json({ error: 'Email not found' }); const email = JSON.parse(fs.readFileSync(filePath, 'utf8')); email.read = true; fs.writeFileSync(filePath, JSON.stringify(email, null, 2)); res.json(email); } catch (err) { res.status(500).json({ error: 'Failed to read email' }); } }); // POST /:id/ack — Mark email as processed router.post('/:id/ack', async (req, res) => { try { const filePath = path.join(INBOX_DIR, `${req.params.id}.json`); if (!fs.existsSync(filePath)) return res.status(404).json({ error: 'Email not found' }); const email = JSON.parse(fs.readFileSync(filePath, 'utf8')); email.processed = true; fs.writeFileSync(filePath, JSON.stringify(email, null, 2)); // Rename to .processed to hide from listing fs.renameSync(filePath, `${filePath}.processed`); res.json({ ok: true }); } catch (err) { res.status(500).json({ error: 'Failed to ack email' }); } } ...[truncated 1605 chars]- Remediation
View remediation
