Uh oh!
There was an error while loading. Please reload this page.
fix(billing): close TOCTOU race in subscription transfer, centralize stripe test mocks - #4239
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview The transfer logic now performs an in-transaction duplicate-org-subscription lookup using Testing infrastructure updates: extends Reviewed by Cursor Bugbot for commit f14eac2. Configure here. |
Greptile SummaryThis PR closes a TOCTOU race in subscription transfers by wrapping the check-then-update logic in
Confidence Score: 4/5Safe to merge for the transfer-route fix; the unresolved new-org creation TOCTOU in organization.ts (flagged in prior review) should be addressed before shipping the webhook path. The route.ts fix is solid and well-tested. The existing-membership branch in organization.ts is now correctly protected. However, the new-org creation path (lines 222-250 in organization.ts) still lacks transaction protection — a P1 concern raised in a previous review that remains open in this iteration. apps/sim/lib/billing/organization.ts — new-org creation path (lines 222-250) is unprotected; apps/sim/lib/billing/organization.test.ts — transaction branch is untested. Important Files Changed
Sequence DiagramsequenceDiagram
participant C1 as Concurrent Request 1
participant C2 as Concurrent Request 2
participant TX as DB Transaction
participant Sub as subscription row
participant Org as organization row
C1->>TX: BEGIN TRANSACTION
C1->>Sub: SELECT ... FOR UPDATE (locks row)
C2->>TX: BEGIN TRANSACTION
C2-->>Sub: blocked — waiting for lock
C1->>Org: SELECT ... FOR UPDATE (locks row)
C1->>Sub: check existingOrgSub
C1->>Sub: UPDATE referenceId → org-id
C1->>TX: COMMIT (releases locks)
C2->>Sub: SELECT ... FOR UPDATE (now acquired)
C2->>Org: SELECT ... FOR UPDATE
C2->>Sub: check existingOrgSub → FOUND
C2->>TX: ROLLBACK (duplicate detected)
Reviews (4): Last reviewed commit: "fix(billing): gate subscription transfer..." | Re-trigger Greptile |
Uh oh!
There was an error while loading. Please reload this page.
waleedlatif1
commented
Apr 20, 2026
Re Greptile P1 (new-org branch race in |
waleedlatif1
commented
Apr 20, 2026
waleedlatif1
commented
Apr 20, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
waleedlatif1
commented
Apr 20, 2026
waleedlatif1
commented
Apr 20, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
Previously the 'already belongs to this organization' early return fired before the org/member lookups, letting any authenticated caller probe sub-to-org pairings without being a member of the target org. Move the noop check after the admin/owner verification so unauthorized callers hit the 403 first.
waleedlatif1
commented
Apr 20, 2026
waleedlatif1
commented
Apr 20, 2026
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit f14eac2. Configure here.
Uh oh!
There was an error while loading. Please reload this page.
Summary
db.transactionwith.for('update')row-locks in bothapp/api/users/me/subscription/[id]/transfer/route.tsandlib/billing/organization.tsto close a TOCTOU race that allowed concurrent requests to attach two subscriptions to the same org.for('update')terminal todbChainMockand document it insim-testing.mdstripe.mock.ts(stripeClientMock,stripePaymentMethodMock,createMockStripeEvent) and migrate billing tests off inline mocksType of Change
Testing
All billing + subscription tests pass (32 tests, 8 files).
Checklist