-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Summary
GET /api/content-items does not scope queries by domainId, which breaks the project’s tenant isolation guarantee and allows cross-tenant listing/count leakage.
Evidence
In src/api/routes.ts:
- Lines 1628-1633 build filters, but no
eq(contentItems.domainId, getDomainId(request))is included. - Lines 1636-1640 run
count(*)and list queries with that unscopedwhereClause.
Relevant snippet:
src/api/routes.ts:1628src/api/routes.ts:1636
Impact
- Any authenticated tenant can enumerate content items from other tenants by using broad filters.
- Response metadata (
total,hasMore) also leaks cross-tenant cardinality. - This directly contradicts
doc/concepts/features.mdmulti-tenant contract (All REST, GraphQL, and MCP APIs filter strictly by the domainId ...).
Proposed Fix
- Add
eq(contentItems.domainId, getDomainId(request))to the conditions array for the route. - Ensure both
count(*)and result queries use the scoped predicate. - Add regression tests in
src/__tests__/api-tenant.test.tsfor:- list isolation across two domains
- metadata isolation (
total,hasMore)
Acceptance Criteria
- Domain A API key cannot observe Domain B content items or counts via
/api/content-items. - New regression tests fail on current code and pass after fix.
- Multi-tenant feature docs remain true for this route.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working