Skip to content

GET /reports/:interviewId exposes full report data without authentication #110

Description

@anshul23102

Summary

GET /reports/:interviewId in server/routes/reportRoutes.js returns the full report — including all answers, scores, feedback, and AI-generated summary — to any caller who provides a valid interview ID, without any authentication or ownership check.

Affected code

router.get("/:interviewId", async (req, res) => {
  const report = await Report.findOne({ interviewId: req.params.interviewId });
  if (!report) {
    return res.status(404).json({ message: "Report not found" });
  }
  res.json(report);  // no firebaseAuthMiddleware, no ownership check
});

The list route (GET /reports/) correctly requires firebaseAuthMiddleware and filters by the authenticated user. The individual report fetch does not.

Impact

  • Anyone who knows (or can enumerate) a valid interviewId can retrieve another user's full AI interview report, including individual answers, AI feedback, performance scores, strengths, and areas of improvement.
  • This data is personal and sensitive; exposure constitutes a privacy violation against every user who has completed an interview.

Suggested Fix

Add firebaseAuthMiddleware and verify ownership before returning the report:

router.get("/:interviewId", firebaseAuthMiddleware, async (req, res) => {
  const decodedToken = req.firebaseUser;
  const user = await User.findOne({ firebase_user_id: decodedToken.uid });
  const report = await Report.findOne({ interviewId: req.params.interviewId });
  if (!report) return res.status(404).json({ message: "Report not found" });
  if (!report.userId.equals(user._id)) {
    return res.status(403).json({ error: "Forbidden" });
  }
  res.json(report);
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions