T05 · Unauthorized Access and Privilege Escalation
- Location
server/index.ts:837- Finding
Unauthenticated Calendar Disclosure and Modification APIs
- Content
View full analysis
{ try { const raw = await fsp.readFile(settingsPath, "utf8"); res.json(JSON.parse(raw)); } catch { res.json({}); } }); app.post("/api/settings", async (req, res) => { try { let current = {}; try { const raw = await fsp.readFile(settingsPath, "utf8"); current = JSON.parse(raw); } catch { // ignore } const next = { ...current, ...req.body }; await fsp.writeFile(settingsPath, JSON.stringify(next, null, 2), "utf8"); res.json(next); } catch (error) { const message = error instanceof Error ? error.message : String(error); res.status(500).json({ error: message }); } }); app.get("/api/calendar", async (_req, res) => { const document = await loadCalendarFromFile(calendarPath); res.json(document); }); app.get("/api/calendar/export", async (_req, res) => { const document = await loadCalendarFromFile(calendarPath); res.type("text/markdown").send(serializeCalendarMarkdown(document)); }); app.post("/api/calendar/import", async (req, res) => { const markdown = req.body?.markdown; if (typeof markdown !== "string" || markdown.trim().length === 0) { res.status(400).json({ error: "Body must include a markdown string" }); return; } try { const parsed = parseCalendarMarkdown(markdown); await saveCalendarToFile(calendarPath, parsed); res.json(parsed); } catch (error) { const message = error instanceof Error ? error.message : "Unable to import markdown"; res.status(400).json({ error: message }); } }); app.post("/api/events", async (req, res) => { // Creates or repla ...[truncated 2472 chars]- Remediation
View remediation
{ await loadCalendarFromFile(calendarPath); }); ``` 2. Require authentication and explicit authorization on every read and mutation route. 3. Do not treat automatically created anonymous sessions as authenticated identities. 4. Restrict CORS to an exact allowlist derived from a validated frontend origin: ```ts cors({ origin: ["http://localhost:5173"], credentials: true }); ``` 5. Add CSRF protection or strict Origin validation to all state-changing routes. 6. Disable or separately protect bulk import and export endpoints. 7. Apply rate limits and request-size limits appropriate to each route. 8. Document that exposing port 8787 through a reverse proxy or container requires TLS and access control. 9. Add integration tests verifying that anonymous and cross-origin callers receive `401` or `403`. ]]>
