fix: address 4 critical issues in promo code endpoint#25
Closed
Njko wants to merge 1 commit into
Closed
Conversation
…error handling, information disclosure) - Add optimistic locking to prevent race condition on cart update - Use safeParse() for response validation instead of parse() - Check rowCount to detect silent failures on cart update - Replace information-disclosing error messages with generic ones Fixes race condition where cart subtotal could be modified between read and update. Uses optimistic locking with updated_at timestamp to ensure consistency. Changes response validation to use safeParse() and handles validation errors explicitly, preventing validation errors from being masked as 500 errors. Adds rowCount check in updateCartWithPromo to detect when cart was deleted between validation and update, preventing silent failures. Replaces error messages that expose cartId and promo code existence with generic error messages to reduce attack surface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Author
|
Closing this PR to address critical security and architecture issues. Will resubmit on fork with comprehensive fixes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes for PR #24
This PR addresses 4 critical issues identified in the code review of PR #24 (promo-code endpoint):
1. Race Condition (app/api/carts/[cartId]/apply-promo/route.ts:102-107)
Problem: Cart subtotal can be modified by another request between read and update
Solution: Added optimistic locking using
updated_attimestampImpact: Ensures discount is calculated against consistent data
Changes:
updateCartWithPromoto acceptpreviousUpdatedAtparameterAND updated_at = $6to check optimistic lock2. Uncaught Zod Validation Error (app/api/carts/[cartId]/apply-promo/route.ts:110-119)
Problem: Uses
.parse()instead of.safeParse(), masks validation failures as 500 errorsSolution: Changed to
.safeParse()with explicit error handlingImpact: Proper error messages for debugging and client feedback
Changes:
.safeParse()3. Silent Failure on Cart Update (lib/db.ts:76-83)
Problem: UPDATE doesn't check rowCount, so cart deletion between validation and update goes undetected
Solution: Check
result.rowCount === 1before returningImpact: Prevents returning success when cart was deleted
Changes:
updateCartWithPromonow returnsPromise<boolean>result.rowCount === 1to verify exactly 1 row was updated4. Information Disclosure (app/api/carts/[cartId]/apply-promo/route.ts:73, 85, 96)
Problem: Error messages expose cartId and promo code existence
Solution: Use generic error messages that don't reveal internal structure
Impact: Reduces attack surface
Changes:
Cart with ID ${cartId}from error messagePromo code "${promoCode}" does not existPromo code "${promoCode}" is expired or inactiveVerification
✅ All 25 tests still pass
✅ TypeScript compilation succeeds with no errors
✅ All good parts of original implementation preserved
✅ Changes are minimal and surgical
Files Modified
app/api/carts/[cartId]/apply-promo/route.ts- Add optimistic locking, use safeParse, generic errorslib/db.ts- Check rowCount, return boolean for update status