foreignTableInApi¶
Group security · Severity Warning · Recommended · Requires Supabase
Diagnostic splinter/security/foreignTableInApi
Note
This rule needs a Supabase database. It is skipped when the Supabase roles don't exist.
Description¶
Detects foreign tables that are accessible over APIs. Foreign tables do not respect row level security policies.
Remediation¶
See the Supabase database linter docs.
How to configure¶
{
"splinter": {
"rules": {
"security": {
"foreignTableInApi": "error"
}
}
}
}
SQL query¶
Show the query
(
select
'foreign_table_in_api' as "name!",
'Foreign Table in API' as "title!",
'WARN' as "level!",
'EXTERNAL' as "facing!",
array['SECURITY'] as "categories!",
'Detects foreign tables that are accessible over APIs. Foreign tables do not respect row level security policies.' as "description!",
format(
'Foreign table \`%s.%s\` is accessible over APIs',
n.nspname,
c.relname
) as "detail!",
'https://supabase.com/docs/guides/database/database-linter?lint=0017_foreign_table_in_api' as "remediation!",
jsonb_build_object(
'schema', n.nspname,
'name', c.relname,
'type', 'foreign table'
) as "metadata!",
format(
'foreign_table_in_api_%s_%s',
n.nspname,
c.relname
) as "cache_key!"
from
pg_catalog.pg_class c
join pg_catalog.pg_namespace n
on n.oid = c.relnamespace
left join pg_catalog.pg_depend dep
on c.oid = dep.objid
and dep.deptype = 'e'
where
c.relkind = 'f'
and (
pg_catalog.has_table_privilege('anon', c.oid, 'SELECT')
or pg_catalog.has_table_privilege('authenticated', c.oid, 'SELECT')
)
and n.nspname = any(array(select trim(unnest(string_to_array(current_setting('pgrst.db_schemas', 't'), ',')))))
and n.nspname not in (
'_timescaledb_cache', '_timescaledb_catalog', '_timescaledb_config', '_timescaledb_internal', 'auth', 'cron', 'extensions', 'graphql', 'graphql_public', 'information_schema', 'net', 'pgmq', 'pgroonga', 'pgsodium', 'pgsodium_masks', 'pgtle', 'pgbouncer', 'pg_catalog', 'pgtle', 'realtime', 'repack', 'storage', 'supabase_functions', 'supabase_migrations', 'tiger', 'topology', 'vault'
)
and dep.objid is null)