From 4d7c19be98130af04651cc9f7ce7c265960a0750 Mon Sep 17 00:00:00 2001 From: Akshara Date: Mon, 22 Jun 2026 13:12:08 +0530 Subject: [PATCH] fix(ai): add Joi schema validation for Gemini API responses --- backend/controllers/aiController.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/backend/controllers/aiController.js b/backend/controllers/aiController.js index 6057eab..9807743 100644 --- a/backend/controllers/aiController.js +++ b/backend/controllers/aiController.js @@ -1,4 +1,5 @@ const { GoogleGenerativeAI } = require("@google/generative-ai"); +const Joi = require("joi"); const { conceptExplainPrompt, questionAnswerPrompt, @@ -9,7 +10,6 @@ const Question = require("../models/Question"); const ai = new GoogleGenerativeAI(process.env.GEMINI_API_KEY); - /** * Generate interview questions and answers using the Gemini AI service. * @route POST /api/ai/generate-questions @@ -103,6 +103,21 @@ const generateInterviewQuestions = async (req, res) => { try { const data = JSON.parse(cleanedText); + + // Validate Gemini response structure + const questionsSchema = Joi.array().items( + Joi.object({ + question: Joi.string().required(), + answer: Joi.string().required(), + }) + ); + const { error: validationError } = questionsSchema.validate( + Array.isArray(data) ? data : data.question + ); + if (validationError) { + return res.status(500).json({ message: "Invalid AI response format", details: validationError.message }); + } + if (Array.isArray(data)) { res.status(200).json({ model: usedModel, question: data }); } else { @@ -187,6 +202,17 @@ const generateConceptExplanation = async (req, res) => { try { const data = JSON.parse(cleanedText); + + // Validate Gemini response structure + const explanationSchema = Joi.object({ + title: Joi.string().required(), + explanation: Joi.string().required(), + }); + const { error: validationError } = explanationSchema.validate(data); + if (validationError) { + return res.status(500).json({ message: "Invalid AI response format", details: validationError.message }); + } + res.status(200).json({ model: usedModel, ...data }); } catch (err) { res.status(500).json({