Review a pull request: ticket attachments

Not solved

Customers can now attach files to support tickets. Upload handling is one of the riskiest features to get wrong — review it.

Level
Practitioner
Estimated time
~25 min
Points
0/85 pts
Questions
0/0 answered
OWASP
A01:2025
OWASP
A05:2025
OWASP
A06:2025
CWE
CWE-434
CWE
CWE-22
CWE
CWE-639
src/routes/attachments.ts0/4 found
import path from 'node:path'
import fs from 'node:fs/promises'
import multer from 'multer'
+const UPLOAD_DIR = path.join(__dirname, '../../public/uploads')
+const upload = multer({ limits: { fileSize: 5 * 1024 * 1024 } })
+
+// Customers attach screenshots and invoices to their support tickets
+router.post('/api/tickets/:id/attachments', requireAuth, upload.single('file'), async (req, res) => {
+ const file = req.file
+ if (!/\.(png|jpe?g|pdf)/i.test(file.originalname)) {
+ return res.status(400).json({ error: 'Only images and PDFs are allowed' })
+ }
+ const ticket = await db.tickets.findById(req.params.id)
+ if (!ticket) return res.status(404).json({ error: 'Not found' })
+ const dest = path.join(UPLOAD_DIR, file.originalname)
+ await fs.writeFile(dest, file.buffer)
+ const url = `/uploads/${encodeURIComponent(file.originalname)}`
+ await db.attachments.insert({ ticketId: ticket.id, url, uploadedBy: req.user.id })
+ res.status(201).json({ url })
+})
+
+router.get('/uploads/:name', requireAuth, (req, res) => {
+ res.type(String(req.query.type || path.extname(req.params.name)))
+ res.sendFile(path.join(UPLOAD_DIR, path.basename(req.params.name)))
+})

Click a line number to flag a defect. The review code appears when every defect is flagged with no false positives.