Skip to content

GET /:interviewId and POST /:interviewId/answer are accessible without authentication #109

Description

@anshul23102

Summary

Two interview routes in server/routes/interviewRoutes.js perform sensitive operations — reading full interview data and submitting analyzed answers — without verifying the caller's identity or ownership of the interview record.

Affected routes

GET /:interviewId (line ~120)

router.get("/:interviewId", async (req, res) => {
  const interview = await Interview.findById(req.params.interviewId);
  res.json(interview);  // no firebaseAuthMiddleware, no ownership check
});

Any unauthenticated caller who knows (or can guess) a valid MongoDB ObjectId can retrieve another user's full interview record, including resume_link, job_description, company_description, and all generated questions.

POST /:interviewId/answer (line ~130)

router.post("/:interviewId/answer", async (req, res) => {
  const interview = await Interview.findById(req.params.interviewId);
  // ... runs AI analysis and appends to report ...
  await report.save();  // no firebaseAuthMiddleware, no ownership check
});

Any unauthenticated caller can submit fabricated answers for any interview ID. The server runs AI analysis and appends the fake answer to the report as if it came from the legitimate owner. If all questions are answered this way the report's finalScore, strengths, and summary are computed from attacker-supplied content.

Contrast with other routes

POST /setup and GET / (list all interviews) correctly use firebaseAuthMiddleware. The two routes above are missing it.

Impact

  • Private interview content (resume links, job descriptions, AI questions) is readable by anyone.
  • Interview reports can be corrupted or forged by third parties without the account holder's knowledge.
  • AI inference costs are incurred for unauthenticated requests with no rate gate.

Suggested Fix

Add firebaseAuthMiddleware to both routes and verify the resolved user._id matches interview.user_id before reading or writing:

router.get("/:interviewId", firebaseAuthMiddleware, async (req, res) => {
  const firebaseUID = req.firebaseUser?.uid;
  const user = await User.findOne({ firebase_user_id: firebaseUID });
  const interview = await Interview.findById(req.params.interviewId);
  if (!interview || !interview.user_id.equals(user._id)) {
    return res.status(403).json({ error: "Forbidden" });
  }
  res.json(interview);
});

Apply the same ownership check to POST /:interviewId/answer.

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