github

Sensitive Column Names Exposed in Supabase

Supabase security checks · MEDIUM

A column that looks like personal data is reachable through the API. Check that policies really limit it.

What goes wrong

Columns named password, api_key, token, ssn and similar in the public schema of a Supabase project suggest sensitive data that the API can reach. The check goes by the column name and by whether the anon or authenticated role has the SELECT privilege on the column.

How it happens

Sensitive values are kept in a public table, and the anon or authenticated role can SELECT the column.

How to find it

List the columns in the public schema with sensitive names that anon or authenticated can SELECT.

SELECT c.relname AS table_name, a.attname AS column_name
FROM pg_attribute a
JOIN pg_class c ON a.attrelid = c.oid
JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE n.nspname = 'public'
  AND c.relkind IN ('r', 'v', 'm', 'p')
  AND a.attnum > 0 AND NOT a.attisdropped
  AND (has_column_privilege('anon', c.oid, a.attnum, 'SELECT')
       OR has_column_privilege('authenticated', c.oid, a.attnum, 'SELECT'))
  AND lower(a.attname) IN (
    'password', 'password_hash', 'hashed_password',
    'secret', 'secret_key', 'api_key', 'api_secret',
    'token', 'access_token', 'refresh_token', 'auth_token',
    'credit_card', 'card_number', 'cvv', 'expiry',
    'ssn', 'social_security', 'national_id', 'tax_id',
    'private_key', 'encryption_key', 'jwt_secret',
    'stripe_key', 'openai_key', 'aws_key'
  );

How to fix it

Move the data to a private schema, encrypt it at rest, or use column-level privileges so the API roles can only read the safe columns.

REVOKE SELECT ON public.<table_name> FROM anon, authenticated;
GRANT SELECT (<safe_column_1>, <safe_column_2>)
  ON public.<table_name> TO authenticated;

Check your own project

Locksoup runs these checks on your Supabase database in about a minute, with a read-only role, and gives you the SQL to fix what it finds.

Check my project