{"id":"GHSA-wrr4-782v-jhwh","aliases":[],"url":"https://o3.security/vulnerability/GHSA-wrr4-782v-jhwh","summary":"neotoma has tenant isolation gap in relationship query endpoints","details":"## Summary\n\nThe `/list_relationships` and `/retrieve_graph_neighborhood` endpoints call `getAuthenticatedUserId` (confirming a valid session exists) but do not pass the resolved user ID into the Supabase query as an `.eq(\"user_id\", userId)` filter. As a result, queries return rows from all users rather than scoping to the authenticated caller's data.\n\n## Affected code\n\n**`/list_relationships`** (`src/actions.ts`):\n- Calls `getAuthenticatedUserId` but does not apply `.eq(\"user_id\", userId)` to the relationships query\n- Uses `.or()` string interpolation for entity ID matching without input validation\n\n**`/retrieve_graph_neighborhood`** (`src/actions.ts`):\n- Same pattern: auth resolved, user ID not applied to query filter\n\n## Affected versions\n\nv0.13.0\n\n## Prerequisites\n\n1. A valid authentication token for the Neotoma instance (attacker must have a legitimate account on the same instance)\n2. A known entity ID belonging to another user (~96 bits of entropy — brute-force not practical)\n\nAn unauthenticated caller is rejected at the auth middleware layer. The gap requires a second user account on the instance.\n\n## Impact\n\nAn authenticated user with a known cross-user entity ID can retrieve relationship edges and graph neighborhood data belonging to another user. No write capability is exposed.\n\n## Severity\n\nLow under current conditions — no multi-tenant deployments exist. Escalates to Medium the moment two or more user accounts share an instance.\n\n## Remediation\n\n1. Add `.eq(\"user_id\", userId)` to all Supabase queries in both handlers\n2. Validate entity ID inputs with `isNeotomaEntityId` before query construction\n3. Replace `.or()` string interpolation with separate scoped `.eq()` calls\n\nFix tracked in #365 (list_relationships) and #366 (retrieve_graph_neighborhood). Gate gap tracked in #372.","published":"2026-06-25T17:46:49Z","modified":"2026-06-25T18:00:08.021100609Z","cvss":null,"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"neotoma","fixedVersion":"0.14.0"}],"fix":null,"references":[{"type":"WEB","url":"https://github.com/markmhendrickson/neotoma/security/advisories/GHSA-wrr4-782v-jhwh"},{"type":"WEB","url":"https://github.com/markmhendrickson/neotoma/issues/365"},{"type":"WEB","url":"https://github.com/markmhendrickson/neotoma/issues/366"},{"type":"WEB","url":"https://github.com/markmhendrickson/neotoma/issues/372"},{"type":"PACKAGE","url":"https://github.com/markmhendrickson/neotoma"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-06-25T18:00:08.021100609Z"}}