Dev.to Security πŸ” Cybersecurity πŸ‘ 0 πŸ“– 3 min read

HIPAA compliance evidence for the database layer on Supabase: RLS, functions, triggers and audit logs

Supabase signs a BAA and has a High Compliance setting for projects that store PHI, which handles the platform. The database layer built on it is a separate matter. RLS policies, functions, triggers and audit tables are

HIPAA compliance evidence for the database layer on Supabase: RLS, functions, triggers and audit logs

Supabase signs a BAA and has a High Compliance setting for projects that store PHI, which handles the platform. The database layer built on it is a separate matter. RLS policies, functions, triggers and audit tables are written by the project team, and a HIPAA review expects evidence that they protect PHI. Supabase’s shared responsibility model puts them on the customer’s side.

What Supabase covers

Encryption at rest and in transit, the BAA, and project settings. The HIPAA guide asks for these to be on:

  • Point in Time Recovery
  • SSL enforcement
  • network restrictions
  • connection logging
  • MFA on every account with access

The Security Advisor warns when any of them is off, and the linter flags patterns like a table in public with RLS off. Neither one runs the policies. They cannot show whether a nurse at one clinic can read another clinic’s visits, or whether a deleted record left a row in the audit table.

What the project owner has to show

A HIPAA review asks three questions about the database:

  • who can reach which patient rows - 164.312(a)(1)
  • is every change to that data recorded - 164.312(b)
  • can anyone alter that record afterwards - 164.312(c)(1)

164.308(a)(8) adds that this is evaluated again whenever the environment changes. On Supabase, the answers live in SQL the team wrote. A screenshot of the policies does not show what the database does when authenticated calls one of those functions. Only running it does.

Producing the evidence with unitautogen hipaa

unitautogen hipaa runs against the local Supabase stack, which is built from the migrations, so no patient data is involved:

bash
supabase start
unitautogen --supabase hipaa --schema public

It generates the tests and the rows they need, runs them as each role the app uses, and rolls the rows back. The tests are written to supabase/tests/seccover/security/, where supabase test db picks them up. The report goes to supabase/tests/seccover/hipaa/public/.

What it checks

  • Access. Functions, views and triggers that run as their owner bypass RLS. Each one is called as two different tenants, with data on both sides, and marked as holding or leaking. Open policies, column grants and PHI leaking through error messages are checked too.
  • Audit log. For every PHI table, and for each of insert, update and delete: did the change leave an audit row, and does that row record who made it. Connection logging does not answer this. It records who connected, not which rows changed.
  • Tampering. For each audit table and each client role: can that role edit, delete or forge rows. A common hole is a security definer function exposed through .rpc() that writes to the audit table, letting any logged-in user write anything into it.
  • Identity. Policies depend on auth.uid(), auth.jwt() or a session setting. The report shows whether a client session can change what those return.

What to fix

The report opens with a ranked β€œWhat to fix” list. There is one row per object, with:

  • the priority: fix now or review
  • the HIPAA section
  • what was found
  • the change that closes it
  • a link to the evidence

When many functions are callable only through PostgreSQL’s default PUBLIC grant, the report says so once above the list and gives the single fix:
sql
REVOKE EXECUTE ON ALL FUNCTIONS IN SCHEMA public FROM PUBLIC;

Every finding is backed by a pgTAP test that can be committed and re-run. Each result is mapped to its 164.312 section, and the report is stamped with a SHA-256 of every file behind it, so any later edit shows.

what to do on every migration

Schema changes reach Supabase as migrations in a PR. Add the hipaa command to the CI job that already runs supabase test db:

bash
supabase start
supabase test db
unitautogen --supabase hipaa --schema public

Every PR then produces a new report, dated and stamped, kept as a build artifact. 164.308(a)(8) asks for an evaluation each time the environment changes. Each of these reports is that evaluation for the database.

Scope

The report gives evidence for RLS policies, functions, triggers and audit logs.

It does not cover:

encryption, backups and network settings - Supabase’s part

More on unitautogen hipaa: https://unitautogen.com/postgresql/unitautogen/hipaa/

πŸ“° Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.