Skip to content

Commit e93a5ca

Browse files
committed
fix(credential-sets): stop leaking open-invite tokens to all users
GET /api/credential-sets/invitations returned every pending, unexpired link-only (null-email) invitation across all organizations, including the bearer token. Any authenticated user could enumerate and accept another org's invitation, joining its credential set (cross-tenant access). Scope the listing strictly to invitations addressed to the caller's own email. Open-link invites remain redeemable only via the out-of-band /credential-account/[token] URL.
1 parent 39d0b56 commit e93a5ca

1 file changed

Lines changed: 5 additions & 5 deletions

File tree

  • apps/sim/app/api/credential-sets/invitations

apps/sim/app/api/credential-sets/invitations/route.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { db } from '@sim/db'
22
import { credentialSet, credentialSetInvitation, organization, user } from '@sim/db/schema'
33
import { createLogger } from '@sim/logger'
4-
import { and, eq, gt, isNull, or } from 'drizzle-orm'
4+
import { and, eq, gt } from 'drizzle-orm'
55
import { NextResponse } from 'next/server'
66
import { getSession } from '@/lib/auth'
77
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
@@ -16,6 +16,9 @@ export const GET = withRouteHandler(async () => {
1616
}
1717

1818
try {
19+
// Scope to invitations addressed to the caller's own email only. Open-link
20+
// (null-email) invites carry a bearer token redeemed via the out-of-band URL
21+
// and must never be listed, or any user could accept another org's invite.
1922
const invitations = await db
2023
.select({
2124
invitationId: credentialSetInvitation.id,
@@ -37,10 +40,7 @@ export const GET = withRouteHandler(async () => {
3740
.leftJoin(user, eq(credentialSetInvitation.invitedBy, user.id))
3841
.where(
3942
and(
40-
or(
41-
eq(credentialSetInvitation.email, session.user.email),
42-
isNull(credentialSetInvitation.email)
43-
),
43+
eq(credentialSetInvitation.email, session.user.email),
4444
eq(credentialSetInvitation.status, 'pending'),
4545
gt(credentialSetInvitation.expiresAt, new Date())
4646
)

0 commit comments

Comments
 (0)