Review submission prevents duplicate submissions from same user per product
Why it matters
Without a unique constraint on (user_id, product_id), a single user can flood your product with five-star reviews — or a malicious competitor can script hundreds of one-star submissions. CWE-799 (Improper Control of Interaction Frequency) names this exact failure. Beyond rating manipulation, duplicate reviews distort your aggregate score fed to schema.org AggregateRating, poisoning the star display that Google indexes. The fix is two-layer: a database constraint that survives any future code path, plus an application-level check that returns a user-facing error immediately.
Severity rationale
High because a missing constraint enables unlimited rating manipulation that corrupts product trust signals and schema.org data without requiring any special privileges.
Remediation
Add a unique constraint in prisma/schema.prisma (or a raw SQL migration) and guard the insert in api/reviews/submit.
-- Migration: enforce one review per user per product
ALTER TABLE reviews
ADD CONSTRAINT unique_user_product UNIQUE (user_id, product_id);
// api/reviews/submit
const existing = await db.reviews.findFirst({
where: { user_id: userId, product_id: productId }
})
if (existing) {
return Response.json({ error: 'You have already reviewed this product' }, { status: 409 })
}
The database constraint is the hard stop; the application check is the early exit that returns a readable error instead of a constraint violation.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Reviews & Social Proof Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-799 — Improper Control of Interaction Frequency
Taxons
History
- 2026-04-18·v1.0.0·Initial import from ecommerce-reviews·automated