Mindbridge ยท track status

SECURITY

Cross-tenant exposure and privilege defects โ€” one tenant's data reachable from another.

Measured 2026-08-16 from gh issue list. Verify before starting โ€” this page has never been published and its prose decays as the track moves; re-measure against live issues before publishing.

Next โ†’ #2968 cross-tenant UNIQUE index โ€” the only p0, and it silently drops a second tenant's rows. Decision #2938 default-grant convention โ€” needs an owner call, not scheduled.
4 open โ€” 1 p0 cross-tenant UNIQUE index, 3 p1 isolation defects: live impersonation poisoning, superuser reads, future-table default grants.
4open on the track
1live person suppressed
3default-grant incidents
~24Ask reads still service-role
Open work Why this order Standing rulings History & forensics
Cross-tenant UNIQUE index โ€” drop-everything
p0 #2968 idx_node_aliases_person_per_source is a cross-tenant UNIQUE index (no tenant_id) second tenant's alias silently dropped All
The UNIQUE index on node_aliases carries no tenant_id, so two tenants cannot hold the same person alias under the same (or a NULL) source_id โ€” the second insert dies on a unique violation, or is silently skipped: silent data loss in the resolution path. Recreated verbatim from the pre-tenant index in 20260320163011_rename_groups_to_sources.sql; tenant_id arrived three days later and the index was never rescoped. Fix: rescope to UNIQUE (tenant_id, lower(alias), COALESCE(source_id, โ€ฆ)), census prod for collisions first, and add a real-DB integration test proving two tenants can hold the same alias.
Impersonation poisoning โ€” live on prod
p1 #2037 ADR-097: impersonation flag keyed on spoofable From address poisons the legitimate mailbox owner forged From stamps real owner Mizo
ADR-097 keys the impersonation verdict โ€” and the is_impersonation stamp on the graph person node โ€” on the spoofable From address, so a phish forging a real mailbox stamps its legitimate owner. Live on prod: the Regina employee Kareem ([email protected]) is flagged is_impersonation=true though he is the real, active owner โ€” 3,886 messages over 2017โ€“2026, bound to a real app login. The verdict correctly identified a phish (sent from oldenglishsuperstores.com) but keyed it on the forged From and stamped the real owner. Systemic: 8 own-domain @pastaregina.com addresses carry impersonation verdicts (7 are harmless role addresses). Fix: key the verdict on the authenticated sending origin (envelope/DKIM), never let one forged message flip a person whose real footprint contradicts it, then backfill to clear the false flags.
Privilege backstops โ€” superuser reads and defaults
p1 #2445 Client end-user read endpoints run as DB superuser (RLS bypassed) โ€” migrate to run-as-user superuser reads have no backstop Mizo
Client end-user reads run as the DB superuser (async_execute_query / service-role) and rebuild tenant + tier isolation with hand-written predicates โ€” one forgotten WHERE tenant_id is a cross-tenant leak with no RLS backstop. The compliant path (async_execute_query_as_user) already exists. Phases 0โ€“2 merged 2026-07-16: the no-silent-admin-fallback guard, the leaf endpoints, and the disclosure-join endpoints. Remaining: Phase 2d (~24 Ask-reachable reads still on service-role), the follow-up to give the eval harness synthetic JWT claims, and the /api/tenants/me/health decision. Acceptance per endpoint: RLS is the primary gate, proven by a real-DB test that blocks cross-tenant and cross-tier reads even with the manual predicate removed.
p1 #2938 Supabase default privileges grant ALL on every new public table to anon/authenticated โ€” close it at the schema, not per object new tables silently world-grantable Latent
Supabase's ALTER DEFAULT PRIVILEGES grants ALL on every new public table to anon/authenticated. tenant_health_snapshot (created 2026-07-10) claimed deny-all but held it via RLS-with-zero-policies while both roles kept every grant โ€” one permissive policy or DISABLE ROW LEVEL SECURITY would have exposed every tenant's health assessment. Three incidents of one failure mode (two function-side lockdowns plus this table), each patched reactively per object. Fix: ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated โ€” affects only future tables, but inverts the repo convention (every client-facing table then needs an explicit GRANT), so it needs an owner call. Cheaper alternative: a check.py-style gate failing any migration that creates a public table without an explicit REVOKE/GRANT.
Why is it in this order?

Applied top to bottom; each rung breaks only the ties left above it.

  • Severity โ€” p0 before p1. The cross-tenant alias index (#2968) is the only p0 on the label.
  • Live, measured harm before latent risk. A defect already suppressing a real person on prod outranks one with no live leak today.
  • A live surface without an RLS backstop before a future-only default. Superuser reads today outrank a default that only affects tables not yet created.

๐Ÿ›‘ What this deliberately ignores: issue age and filing order; how cheap or well-understood a fix looks; how much of an issue is already merged.

Standing rulings

None recorded โ€” track:security carries an empty decided list in track-order.json. The load-bearing open ruling is the default-grant convention decision (#2938); record it in track-order.json when made, so the next session reads it instead of re-asking.

History โ€” how each defect was found

#2968 was found while draining the _v1_substrate_xfail allowlist (batch 4), not caused by that work. The index was recreated verbatim from its pre-tenant form in 20260320163011_rename_groups_to_sources.sql; tenant_id landed three days later (20260323000000_tenant_id_everywhere.sql) and the recreated index was never rescoped.

#2037 surfaced during the Regina disclose() + email-spoofing audit (docs/investigations/2026-06-21-regina-email-spoofing-report.md), on the ADR-097 impersonation track.

#2445 surfaced during the ADR-096 read-projection work (#2437). Phases 0โ€“2 merged 2026-07-16; Phase 2d and the follow-up remain.

#2938 surfaced by the adversarial review on #2936 (ADR-135 stage 4a). tenant_health_snapshot sat world-grantable for three weeks before #2936 revoked it for that one table.

Forensics โ€” the production evidence

Impersonation (#2037): person node 61b97263-dd6f-484e-aa32-20d361e33b5c ("Kareem") is flagged is_impersonation=true on prod (tenant e9d96b09โ€ฆ). The verdict that flagged it cites a message actually sent from oldenglishsuperstores.com โ€” a correct phish identification keyed on the forged From and stamped onto the real owner. No evidence or reason is stored on the node (impersonation_evidence/impersonation_reason are null), so the suppression is silent.

Default grants (#2938): measured 2026-08-01 on tenant_health_snapshot โ€” relacl showed anon=arwdDxtm and authenticated=arwdDxtm (every privilege) with RLS enabled and zero policies.