Fix: Resolve IDOR on Reply Creation API#279
Conversation
|
@riddhima25bet10005-a11y is attempting to deploy a commit to the Karan Mani Tripathi 's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Hi @knoxiboy |
|
@knoxiboy reviewed? |
|
Hey @knoxiboy |
There was a problem hiding this comment.
Pull request overview
This PR aims to fix an IDOR vulnerability in POST /api/replies by ensuring the requester is authorized (classroom member) before allowing reply creation for classroom-scoped doubts.
Changes:
- Added a classroom membership check against
membershipsTablewhen creating a reply for a doubt with aclassroomId. - Added a 404 response when the target doubt does not exist.
- Updated the footer to include additional “Resources” links (not mentioned in the PR description).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
app/api/replies/route.ts |
Adds doubt existence check and classroom membership authorization gate for reply creation. |
components/Footer.tsx |
Adds new footer navigation links and refactors link rendering logic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { | ||
| title: "Resources", | ||
| links: [ | ||
| { label: "Public Doubts", href: "/public-rooms" }, | ||
| { label: "Bookmarks", href: "/bookmarks" }, | ||
| { label: "Privacy Policy", href: "/privacy-policy" }, | ||
| { label: "Terms of Service", href: "/terms-of-service" }, | ||
| { label: "About", href: "/about" }, |
| import { repliesTable, doubtsTable, classroomsTable, replyLikesTable, usersTable, membershipsTable, notificationsTable } from "@/configs/schema"; | ||
| import { eq, asc, sql, and } from "drizzle-orm"; | ||
| import { NextResponse } from "next/server"; | ||
| import { auth, currentUser } from "@clerk/nextjs/server"; |
| if (doubt.classroomId) { | ||
| const [membership] = await db.select().from(membershipsTable).where( | ||
| and(eq(membershipsTable.userEmail, email), eq(membershipsTable.classroomId, doubt.classroomId)) | ||
| ); |
| // 1. AI Moderation Check | ||
| if (content) { | ||
| const moderation = await moderateContent(content); | ||
| const violationError = await handleModerationViolation(email, content, moderation); | ||
| if (violationError) { | ||
| return NextResponse.json({ error: violationError }, { status: 400 }); | ||
| } | ||
| } | ||
|
|
||
| // Security: Check if it's a teacher doubt | ||
| // Security: Check if it's a teacher doubt and verify classroom membership | ||
| const [doubt] = await db.select().from(doubtsTable).where(eq(doubtsTable.id, doubtId)); | ||
| if (doubt?.type === 'teacher') { | ||
|
|
||
| if (!doubt) { | ||
| return NextResponse.json({ error: "Doubt not found" }, { status: 404 }); | ||
| } | ||
|
|
||
| if (doubt.classroomId) { | ||
| const [membership] = await db.select().from(membershipsTable).where( | ||
| and(eq(membershipsTable.userEmail, email), eq(membershipsTable.classroomId, doubt.classroomId)) | ||
| ); | ||
| if (!membership) { | ||
| return NextResponse.json({ error: "Access denied to this classroom" }, { status: 403 }); | ||
| } | ||
| } |
| if (doubt.classroomId) { | ||
| const [membership] = await db.select().from(membershipsTable).where( | ||
| and(eq(membershipsTable.userEmail, email), eq(membershipsTable.classroomId, doubt.classroomId)) | ||
| ); | ||
| if (!membership) { | ||
| return NextResponse.json({ error: "Access denied to this classroom" }, { status: 403 }); | ||
| } | ||
| } |
|
Hi there! 👋 Thanks for your contribution to DoubtDesk. It looks like there are currently some merge conflicts between your branch and the Once the conflicts are resolved and the PR is clean, we'll be able to merge it! |
68ef24e to
7db334e
Compare
Signed-off-by: Riddhima Saluja <riddhima.25bet10005@vitbhopal.ac.in>
…s on fix-267 branch Signed-off-by: Riddhima Saluja <riddhima.25bet10005@vitbhopal.ac.in>
7db334e to
e5062ec
Compare
|
@knoxiboy |
# Conflicts: # app/api/replies/route.ts
knoxiboy
left a comment
There was a problem hiding this comment.
Code changes look excellent. Thank you for your contribution to DoubtDesk! 🎉
Description
Fixes an Insecure Direct Object Reference (IDOR) vulnerability in the \POST /api/replies\ endpoint where an unauthenticated or unauthorized user could post replies to doubts belonging to classrooms they were not enrolled in.
The endpoint now correctly validates the classroom membership of the requesting user when creating a reply on a classroom-scoped doubt.
Fixes #267
Changes Made
Checklist