react-doctor/supabase-client-owned-authz-field
When the client writes authorization columns (`ownerId`, `orgId`, `role`, `isAdmin`) to Supabase, an attacker can forge them and escalate their own access.
- Category: Security
- Severity: error
- Source:
oxlint-plugin-react-doctor - Framework: global
- Enabled when: client (browser-bundled) production source files; server dirs (api/backend/server/middleware/route/functions/lambdas/workers, *.server.*) skipped
- Tags: security-scan
- Default: Enabled
Validation prompt
Use this to decide whether a fired diagnostic is real or a false positive.
Fires in client (browser) code only when BOTH signals are present: (a) a Supabase write — supabase…insert(/upsert(/update(, or .from(...) followed by insert/upsert/update( with an object/array-literal argument — that includes an authorization column (ownerId, creatorId, userId, orgId, tenantId, role, or isAdmin), and (b) a sensitive-field name (ownerId|creatorId|userId|uid|providerId|orgId|tenantId|teamId|workspaceId|role|roles|isAdmin|admin, with Id/ID variants) appearing in the file. The two-signal gate avoids flagging files that merely mention these names. FALSE POSITIVE: the written value comes from a trusted server context the client only echoes back (an authenticated session id, or a column an RLS with check policy independently re-verifies) rather than raw client input — confirm whether RLS actually constrains the column server-side.
Fix prompt
Use this once validation confirms the diagnostic is real.
Stop sending owner, org, tenant, or role columns from the client; let the database set them. Default user_id to auth.uid(), derive org and role from server-owned membership rows, and enforce it with an RLS with check policy so a forged ownerId or role in the payload is rejected. Move any genuinely privileged write behind a server route or a security definer Postgres function that validates the actor.
Related rules
More Security rules from the rules reference:
react-doctor/supabase-rls-policy-risk: A Supabase policy that disables row-level security, exposes the service role, or uses a `(true)` write predicate lets clients read or modify data that is not theirs.react-doctor/supabase-table-missing-rls: Supabase table created without Row Level Securityreact-doctor/svg-filter-clickjacking-risk: Applying CSS or SVG filters over a cross-origin iframe can be used for clickjacking or to read pixels from framed content the attacker should not see.react-doctor/tanstack-start-get-mutation: Use `createServerFn({ method: 'POST' })` for data modifications — GET requests can be triggered by prefetching and are vulnerable to CSRFreact-doctor/tanstack-start-no-secrets-in-loader: Loaders are isomorphic (run on both server and client). Wrap secret access in `createServerFn()` so it stays server-only