Potential cross-tenant access through SECURITY DEFINER function
- Affected:
- public.get_invoice(uuid)
- Category:
- Tenant Isolation
- Confidence:
- high
- First detected:
- 2026-08-12 11:04Z
- Last verified:
- 2026-08-16 09:41Z
Summary
public.get_invoice(uuid) runs with the privileges of its owner, is executable by authenticated, and reads public.invoices without an ownership constraint in the evaluated path.
Why this matters
Row Level Security on public.invoices is not applied inside a definer-rights function. Any signed-in user who can guess or enumerate an identifier can retrieve records belonging to another organization, and the function is reachable directly over the REST RPC endpoint.
Evidence
- Role
- authenticated
- Object
- public.get_invoice(uuid)
- Function security
- SECURITY DEFINER
- search_path
- public, pg_temp
- Executable by
- authenticated
- Target relation
- public.invoices
- Exposed via RPC
- true
- Tenant validation
- No qualifying ownership constraint detected in evaluated path
Facts above were derived by the scanner from database metadata. No model output is involved in the verdict.
Technical details
pg_proc.prosecdef is true and EXECUTE is granted to authenticated. The function body selects from public.invoices, whose tenant column is never compared against the caller's resolved tenant. Because the function owner bypasses RLS, the table's policies do not constrain the result set.
Attack path
internet → authenticated → rest → rpc → fn:public.get_invoice(uuid) → public.invoices
recommended remediation
Unlock Full Audit (Demo)
Constrain the definer function to the caller's tenant, or drop definer rights and let RLS apply.
Current
Function: public.get_invoice(uuid) Security: DEFINER Reads: public.invoices
Recommended Review
This function reads tenant data using definer privileges but does not validate the caller's identity. DBXray cannot automatically generate the missing tenant constraint because it requires application-specific authorization logic. Either constrain the definer function to the caller's tenant, or drop definer rights (SECURITY INVOKER) and let RLS apply.
Expected security effect
- Authentication required
- Tenant ownership enforced inside the definer boundary
- Cross-tenant access path removed
- EXECUTE narrowed to authenticated
No migration generated — application intent required.
Compatibility risk
high
Internal jobs that call this function outside a user session will resolve no tenant and receive zero rows. Give them a separate service-role path.
