What we request and store
Automated software. This page lists what the current code does.
16,326 Supabase databases with at least one anonymously readable table, out of roughly 300,000 domains UpGuard probed; over half showed indicators of personal data.
Published 24 Sep 2026 by UpGuard. Researcher Matt Palmer is credited by BleepingComputer. The figure is from UpGuard's post.
- ✓Nothing is scanned until you prove you own the domain.
- ✓The free scan sends GET and HEAD only: up to 60 requests to your site, up to 45 to its backend.
- ✓The Proof Report runs as two test accounts you create. A service_role key is refused.
- ✓Results are kept 90 days: counts and masked ids, never row text.
Before you prove the domain
A scan of files, git or the database does not start. A public-surface preview is one home-page GET, not a scan. It reads the first 1 KB of the homepage and does a DMARC lookup. It does not request /.git, /.env or Supabase.
Free scan: every request
The free scan is read-only. GET and HEAD only, from user-agent PreflightBot/0.1 (+https://preflightbot.com), after the signed-in owner has verified the domain. Up to 60 requests to the site and up to 45 to its backend. Nothing is written to the app. There is no sign-in to your app.
- GET the homepage. If HTTPS fails, one HTTP fallback.
- GET same-origin script bundles, up to 16. GET source maps, first 2 KB, for the first few bundles.
- GET one random path, used as a soft-404 baseline.
- GET these paths, first 2 KB: /.env, /.env.local, /.env.production, /.git/HEAD, /.git/config, /.DS_Store, /backup.zip, /site.zip, /backup.sql, /dump.sql.
- GET /server-status, /phpinfo.php, /actuator/env, /debug/vars, /_debugbar/open.
- GET / with a foreign Origin, following same-origin redirects only. HEAD http:// the host, redirects not followed.
- If the public bundle contains a Supabase URL and anon key: GET /rest/v1/ (OpenAPI), HEAD /rest/v1/<table>?select=* with Prefer: count=exact for up to 35 tables, GET /auth/v1/settings, GET /storage/v1/bucket.
- If the bundle contains Firebase: GET /.json?shallow=true on the Realtime Database. Firestore is not checked.
- DNS TXT, MX and _dmarc through Cloudflare DNS-over-HTTPS, not through your server. POST to api.osv.dev for library versions found in the bundle; that request does not go to your server.
Proof Report: every test
These run together, as two test accounts you create. They are not individually switchable yet. Webhook and edge-function checks do not run: the report marks them not run, and Preflight does not send an event to a webhook URL or call an edge function.
- Cross-user read. Signs in as test account A and tries to read B's rows. Keeps a count and up to three masked ids (first four characters, an ellipsis, last four). Row text is not kept.
- Canary write. Inserts a row marked preflight-canary-<scan id> and deletes by that marker. If the delete is blocked, at most one such row is left per table, with the SQL to remove it.
- Privilege fields. Patches is_admin, plan or credits on the test account and restores them with a second request. There is no database transaction. A crash between the two can leave the change in place.
- Database functions. Calls the functions it finds in your API, as test account A with B's id, and with no sign-in when a function takes no arguments. Names that look state-changing (delete, send, charge, reset and the like) are skipped and listed. A function with side effects its name doesn't reveal will run.
- Storage file. Uploads one small file marked preflight-canary-<scan id> to a bucket, overwriting an existing file only if its name matches the marker, and deletes it by that marker when the policies allow. If it cannot, the report lists it.
- AI calls. At most two calls to database functions whose names look like AI or credit-spend calls, once without sign-in and once as a test account. If a function debits credits, those calls can spend them.
Test-account passwords are used only during the run and are not stored. Use throwaway accounts. The public anon key from your bundle is used for discovery.
What we store
- Reports: 90 days, then deleted. You can delete one sooner from the report page.
- Check results: status codes, sizes, counts, masked secrets, up to three masked ids. Not row text.
- On sign-up and sign-in: your email, the domains you add, the app URL if you add one, your country, a hashed IP used for rate limits, and the link that brought you here.
- Visit counts by Cloudflare Web Analytics and Piqo, both without cookies.
- Anonymous, aggregate scan statistics may be published, with no domain names and no per-site details.
- To delete your data, email support@preflightbot.com.
What Preflight never does
- Never scans a site you haven't proven you own.
- Never asks for or accepts a service_role key.
- Never keeps your users' row text. Keys are masked.
- Never stores test-account passwords.
- Never claims a clean report is a guarantee. Every report lists what it didn't check.
- Never runs the paid tests without a ticked consent box and a proven Supabase project.
What built-in checks don't tell you
Use your platform's built-in checks. They're free and good. Supabase's Security Advisor lints your database configuration, and Lovable's Quick and Deep security scans (its docs, as of 22 October 2026) review your database access rules, dependencies and application code. Both read how things are set up. Neither signs in to your live app as two users and tries things. That's the part Preflight adds.
- Policies that look fine but don't hold. A select policy like auth.uid() is not null lets every signed-in user read every row. As of 22 October 2026, Supabase's always-true lint covers update, delete and all policies, not select (see its source), and a config check doesn't try signing up. Preflight does.
- What a user can change. Self-granted plan or credits, and an insert that lands as someone else, shown by trying them on a preflight-canary row. Forged payment events and edge functions that skip auth are listed as not checked.
- Your deployed site, in one report. Headers, exposed files, bundle secrets, TLS and email DNS, whichever tool built the app.
Other tools test parts of this too. Compare. Webhook and edge-function checks do not run.