feat(tags): add validation to ensure tags belong to the project to prevent IDOR

This commit is contained in:
Yusuf İpek
2026-04-10 21:40:48 +03:00
parent eca3f92e71
commit 1be0e6d6fa
2 changed files with 22 additions and 1 deletions
+12 -1
View File
@@ -173,7 +173,18 @@ export async function PATCH(request: NextRequest, { params }: RouteParams) {
const updateData: Record<string, unknown> = {};
if (content !== undefined && typeof content === 'string') updateData.content = content.trim();
if (tagId !== undefined) updateData.tagId = tagId;
if (tagId !== undefined) {
// Verify tag belongs to this project to prevent cross-project tag leakage (IDOR)
if (tagId !== null) {
const tag = await db.commentTag.findFirst({
where: { id: tagId, projectId: project.id },
});
if (!tag) {
return apiErrors.badRequest('Tag not found');
}
}
updateData.tagId = tagId;
}
if (annotationData !== undefined) {
if (annotationData === null) {
updateData.annotationData = null;
@@ -293,6 +293,16 @@ export async function POST(request: NextRequest, { params }: RouteParams) {
return apiErrors.badRequest('Guest name is required for guest comments');
}
// Verify tag belongs to this project to prevent cross-project tag leakage (IDOR)
if (tagId) {
const tag = await db.commentTag.findFirst({
where: { id: tagId, projectId: project.id },
});
if (!tag) {
return apiErrors.badRequest('Tag not found');
}
}
if (voiceUrl && !SAFE_AUDIO_PATH.test(voiceUrl)) {
return apiErrors.badRequest('Voice URL must reference an uploaded audio file');
}