Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/web/app/api/teams/[team]/upgrade/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ async function getHandler(req: NextRequest, { params }: { params: Promise<Params
throw new HttpError({ statusCode: 402, message: "Payment required" });
}

// Not all sessions carry "teamId": API v2 uses "pendingPaymentTeamId" and legacy sessions predate it.
const sessionTeamId = checkoutSession.metadata?.teamId;
if (sessionTeamId && Number(sessionTeamId) !== id) {
throw new HttpError({ statusCode: 400, message: "Checkout session does not match team" });
Comment on lines +49 to +51
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use presence check for teamId and reject malformed values.

On Line 50, the truthy guard (if (sessionTeamId && ...)) skips validation when teamId is an empty string, even though metadata is present. That weakens the new consistency check. Validate when the key is defined, and fail on non-integer values.

Suggested fix
-    const sessionTeamId = checkoutSession.metadata?.teamId;
-    if (sessionTeamId && Number(sessionTeamId) !== id) {
-      throw new HttpError({ statusCode: 400, message: "Checkout session does not match team" });
-    }
+    const sessionTeamId = checkoutSession.metadata?.teamId;
+    if (sessionTeamId !== undefined) {
+      const parsedSessionTeamId = Number.parseInt(sessionTeamId, 10);
+      if (!Number.isInteger(parsedSessionTeamId) || parsedSessionTeamId !== id) {
+        throw new HttpError({ statusCode: 400, message: "Checkout session does not match team" });
+      }
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const sessionTeamId = checkoutSession.metadata?.teamId;
if (sessionTeamId && Number(sessionTeamId) !== id) {
throw new HttpError({ statusCode: 400, message: "Checkout session does not match team" });
const sessionTeamId = checkoutSession.metadata?.teamId;
if (sessionTeamId !== undefined) {
const parsedSessionTeamId = Number.parseInt(sessionTeamId, 10);
if (!Number.isInteger(parsedSessionTeamId) || parsedSessionTeamId !== id) {
throw new HttpError({ statusCode: 400, message: "Checkout session does not match team" });
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/app/api/teams/`[team]/upgrade/route.ts around lines 49 - 51, The
current guard uses a truthy check on checkoutSession.metadata?.teamId
(sessionTeamId) which treats empty string as absent and skips validation; update
the logic in route.ts to check for the presence of the key (e.g., metadata
hasOwnProperty or sessionTeamId !== undefined) and then validate that
sessionTeamId is a valid integer (use Number/parseInt and Number.isInteger or
/^\d+$/) before comparing to id; if the value is missing, non-numeric, or not
equal to id, throw the existing HttpError({ statusCode: 400, message: "Checkout
session does not match team" }) so malformed values are rejected and only valid
integer team IDs are accepted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedroccastro sir, should we address this?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

}

let team = await prisma.team.findFirst({
where: { metadata: { path: ["paymentId"], equals: checkoutSession.id } },
});
Expand Down
Loading