fix(cards): validate platformLink ownership before creating card links#183
Open
Ridanshi wants to merge 2 commits into
Open
fix(cards): validate platformLink ownership before creating card links#183Ridanshi wants to merge 2 commits into
Ridanshi wants to merge 2 commits into
Conversation
Collaborator
|
Hey, @Ridanshi could please mention the issue it closes in the PR description. |
Author
|
Sure, thanks for pointing it out. I’ve updated the PR description to explicitly mention the linked issue and added the closing reference ( |
Harxhit
reviewed
May 20, 2026
Collaborator
There was a problem hiding this comment.
Error handing can be better for DB logic.
Author
There was a problem hiding this comment.
Thanks for the review. I’ll improve the DB-side error handling around the ownership validation flow and update the PR with a cleaner failure-handling path shortly.
POST /api/cards and PUT /api/cards/:id accepted arbitrary platformLink IDs without verifying they belong to the authenticated user. Because platformLink IDs are exposed in the public profile API, any authenticated user could attach another user's verified social links to their own card, enabling impersonation. Add a pre-flight ownership check before each CardLink write. A single indexed query confirms every requested ID exists with userId = current user. If the count does not match, the request is rejected with 403 before any write occurs. Covered by new tests in src/__tests__/cards.test.ts.
Following reviewer feedback on the IDOR ownership-validation PR:
- Wrap all five route handlers in try/catch so unexpected DB exceptions
always return { error: 'Internal server error' } rather than leaking a
raw 500 from Fastify's default error handler.
- Replace the bare deleteMany + createMany pair in PUT /cards/:id with a
Prisma \ call. Previously a failed createMany after a
successful deleteMany left the card with no links (partial write).
The transaction rolls both operations back atomically on any failure.
- Replace the bare updateMany + update pair in PUT /cards/:id/default
with a \ for the same reason: if the second write failed the
user had zero default cards until the next successful update.
- Add structured app.log.error({ err }) calls in every catch block so
DB failures are observable in logs without exposing internals to clients.
Tests added (cards.test.ts):
- DB error during ownership validation -> 500, no write attempted
- DB error during card.count / card.create -> 500
- DB error during card.findFirst in PUT -> 500
- Transaction failure mid-flight (createMany throws) -> 500, card retains
existing links
- DELETE: card.delete throws -> 500
- PUT /default: transaction failure (update throws after updateMany) -> 500
- PUT /default: success path verifies both ops run inside \
- PUT /:id: success path verifies deleteMany + createMany inside \
b96c782 to
8da2ea1
Compare
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.
Summary
Fixes an IDOR vulnerability where authenticated users could attach another user's platform links to their own DevCard profile by supplying arbitrary
platformLinkIDs.Previously, the backend trusted client-provided
linkIdsand created/updatedCardLinkrecords without validating ownership.This allowed users to:
Fix
Added strict ownership validation before creating or updating
CardLinkrecords.The implementation now:
linkIds,403 Forbidden,Validation is now enforced for:
POST /api/cardsPUT /api/cards/:idNo schema changes or API contract changes were introduced.
Testing
Added focused authorization tests covering:
linkIds,Also verified:
Security Impact
This patch restores proper ownership enforcement for platform link attachment flows and prevents profile impersonation through unauthorized link association.
Closes #149