Keys and incidents

What to do in the first hour after a leak

In the first hour after you find a leak, contain it before you investigate it: revoke any exposed secret key, close the open table or bucket, then save the logs before they expire, check whether anyone used the hole, and write down a timeline. Decisions about telling users or a regulator come after you know what was exposed, but in the UK and EU the clock for reporting can start the moment you become aware.

TL;DR

  • Minutes 0–15: contain. Rotate exposed secret keys; lock the open table with the narrowest change that works.
  • Minutes 15–30: preserve. Export API, auth and provider logs now; retention can be short.
  • Minutes 30–45: assess. What data, whose, how many rows, was it accessed, and since when.
  • Minutes 45–60: record and decide. A written timeline, who needs to know, and whether the breach is reportable.

This guide is the whole first hour: keys, data and people. For the hands-on SQL that closes an open Supabase table, use Leaking right now? alongside it.

Minute 0: what kind of leak is it?

You foundIt’s aFirst move
A secret key in code, history or the browser bundleKey leak (PL-009, PL-010, PL-011)Rotate it
A table anyone (or any sign-up) can readData exposure (PL-001, PL-002, PL-008)Close the policy
Files in a public or open bucketData exposure (PL-007, PL-015)Make the bucket private
Someone tells you they downloaded your dataConfirmed breachAll of the above, and treat it as accessed

Start a plain text file now and write the time you found it, how, and what you saw. You will rely on this later and memory is poor under stress.

Minutes 0–15: contain

Exposed secret keys

Rotate first, investigate second. A Supabase service role or secret key gives full access to your database, so it comes before everything else. AI keys run up bills; payment keys reach customer and payment data. Where to rotate each kind of key.

An open table

Make the narrowest change that stops outsiders reading it. If you’re not sure what the app needs, revoking the API roles’ read access to that one table stops the leak at the cost of breaking the pages that use it, which is usually the right trade for an hour:

emergency-lock.sql
-- Stop logged-out visitors and signed-in users reading this table via the API.
-- Your server code using the service role key is unaffected.
revoke select on public.customers from anon, authenticated;

Then save the same change as a migration so a later deploy doesn’t undo it. Once things are calm, replace it with proper owner policies and grant read access back (RLS policies explained).

An open bucket

emergency-bucket.sql
update storage.buckets set public = false where id = 'documents';

Broad policies on storage.objects also need dropping; see storage bucket policies.

Minutes 15–30: preserve the evidence

Logs are how you find out whether anyone used the hole, and many hosts keep them only briefly. Export now, before you change much else:

  • Supabase logs: in the dashboard’s logs explorer, look at API (edge) logs for requests to the exposed table’s path (/rest/v1/customers), auth logs for unusual sign-ups, and storage logs for downloads. Save the results; retention depends on your plan.
  • Provider dashboards: usage and request logs for any rotated key (AI usage, Stripe’s request logs).
  • Your host: Vercel, Netlify or similar request logs if they front your API routes.
  • Git: the commit that introduced the problem and its date (git log -S 'policy name' --all finds when a string was added).

Don’t delete the leaky policy’s history, rows or files to “clean up”: you need them to work out what was exposed.

Minutes 30–45: assess what was exposed

Answer five questions and write each answer down with how you know it:

  1. What data? List the columns: emails, phone numbers, addresses, dates of birth, payment details, documents, messages.
  2. Whose, and how many? select count(*) from public.customers; gives the upper bound.
  3. To whom? Anyone with the public key, anyone who signed up, or someone with the repo.
  4. Since when? The date of the migration or commit that opened it.
  5. Was it used? Requests in the logs you didn’t make, sign-ups you don’t recognise, unexpected spend on a rotated key. No evidence of access is not proof of no access, especially if logs don’t reach back to the start date.

Minutes 45–60: record and decide who to tell

Turn your notes into a short timeline: when it was introduced, when found, what you changed and when, what the logs show. Then decide, with advice if you can get it:

  • Regulators. Under the UK GDPR and the EU GDPR, a personal data breach that is likely to put people at risk must be reported to the regulator (in the UK, the ICO) within 72 hours of becoming aware of it. Not every exposure is reportable; record your reasoning either way. Other countries and US states have their own rules.
  • Affected people. If the risk to them is high (identity documents, financial data, anything enabling fraud), they generally need to be told directly, in plain language, with what to watch for.
  • Partners and providers. Payment providers and some platforms have their own reporting expectations for leaked keys or card data.
  • Your team and investors, briefly and factually.

This is general information, not legal advice. If personal data may have been accessed, get advice from a data-protection professional early; the ICO also runs a helpline for small organisations.

After the first hour

  • Replace emergency changes with proper fixes, tested as a visitor, a stranger and the owner.
  • Look for the same mistake elsewhere: the pattern that opened one table usually opened others.
  • Add the check that would have caught it to your release routine, and re-check on a schedule.
  • Write a short, blameless note of what happened and what changed.

Sources

The checks behind this guide, each with example code, a self-check and the fix.

Free check

Check your app for this, free.

Paste your public repo. PatchLabs rebuilds your database from its migrations, tests it as a visitor, a stranger and the owner, reads the code for keys and risky patterns, and hands you the fix.

Free for your first appNever touches your database

Written by Manraj Singh Dhillon. Last checked 10 Nov 2026. Code samples are synthetic and run against your own project; nothing here names a real app. Spotted a mistake? Tell us.