bug(gateway): projects list endpoint returns ALL projects regardless of ownership — data privacy violation #197
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Severity: HIGH — Data Privacy
The
GET /api/projectsendpoint returns every project in the database to any authenticated user, regardless of ownership or team membership. Clicking on a project then fails with "Project does not belong to the current user" because the detail endpoint correctly enforces ownership.This is a data privacy violation: users can see project names, descriptions, statuses, and metadata for projects they do not own and have no access to.
Root Cause
Two separate bugs working together:
Bug 1: Unscoped list query
ProjectsController.list()callsbrain.projects.findAll()with no user filtering:Compare with conversations and missions which do it correctly:
Bug 2: Ownership lost after team/workspace migration
The "Project does not belong to the current user" error on detail view suggests that existing projects have
owner_idvalues that no longer match the current user's session ID. This could be caused by:ON DELETE SET NULL)owner_type = 'team') whereassertOwneronly checksowner_id, not team membershipFix Required
Immediate (list scoping):
Immediate (ownership check):
assertOwnerneeds to also check team membership for team-owned projects, not justownerId:Data audit:
Run
SELECT id, name, owner_id, team_id, owner_type FROM projectsto verify ownership state. Check if any projects haveNULLowner_id (orphaned by cascade).Location
apps/gateway/src/projects/projects.controller.ts:31— unscopedlist()packages/brain/src/projects.ts:8—findAll()returns all rowsapps/gateway/src/auth/resource-ownership.ts—assertOwnerlacks team membership checkImpact