You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(security): enforce project-membership authorization across all tRPC routers (IDOR) (#3129)
Closes#3122.
The Drizzle client connects as an RLS-exempt Postgres superuser, so authorization
must be enforced in tRPC procedure code. `verifyProjectAccess` existed but was
applied to only a handful of procedures; every other project-scoped procedure
trusted a client-supplied id (projectId / conversationId / branchId / sandboxId /
deploymentId / verificationId / ...), so an authenticated user could read or
mutate another user's data.
This audits the whole tRPC surface and closes it with one resolve-then-verify
pattern, all sharing a merged "Unauthorized or not found" error so the checks
can't be used to enumerate resource existence.
Helpers (project/helper.ts):
- verifyProjectAccess (existing) + verifyConversationAccess, verifyMessagesAccess,
verifyBranchAccess, verifyCanvasAccess, verifyFrameAccess, verifyInvitationAccess
- verifySandboxAccess — resolves sandbox -> branch/project; a sandbox not yet tied
to a project (fresh create/fork/template/import, before a branch row exists) is
allowed so blank-project / local-import / fork flows keep working
- verifyDeploymentAccess, verifyDomainVerificationAccess
- listAccessibleSandboxIds — scopes sandbox.list (whose provider call returns the
whole account) to the caller's own sandboxes
Routers hardened: project, chat (conversation/message/suggestion), branch, frame,
settings, createRequest, sandbox, publish (deployment + unpublish), domain
(preview/custom/verification), user (getById self-only, upsert pinned to session),
subscription, usage, user-canvas, user-settings.
Also: auth checks moved out of catch-and-return-false blocks so denials propagate
as errors; verifyMessagesAccess dedupes ids so a bulk op with a repeated id isn't
falsely rejected; getPreviewProjects throws TRPCError.
Adds unit tests for the authorization helpers (project/helper.test.ts, 19 cases).
Web-client typecheck passes.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
0 commit comments