Sample Full Report
This is what US$19 gets you
Below is real Abbi Labs scanner output from our own test app, which we built to leak on purpose (fake keys, fake data). The free scan shows your grade, the counts and your worst finding. The Full Report unlocks every finding like the ones below, with what it means, what an attacker could do, how to fix it, and a prompt you can paste into Cursor, Lovable or Bolt.
Full Report, US$19 once per app
Every finding and fix, plus 30 days of re-scans to confirm your fixes worked. Scan free first, then unlock only if it finds something.
Sample scan of our test app. Secrets are masked in every report. Indicative passive scan, not a pentest.
criticalStripe live secret key exposed in client code
Show details ▾/assets/app.js · sk_liv…0000 (40 chars)
Stripe live secret key exposed in client code
Show details ▾A Stripe live secret key is sitting in a file your site serves to every visitor, so anyone can copy it.
Critical. Blast radius: Your Stripe account can be charged, refunded and read: every customer, payment and payout record, and refunds or new charges can be issued against your balance.
If this key is live (we matched its format; we did not use it): 1) an attacker opens your site, views the page source or JS bundle (/assets/app.js) and copies the key; 2) they use it from their own machine with the provider's normal API, outside your app and its limits; 3) they list your customers and payments, issue refunds to drain your balance, or create charges and payment links in your name. Bots scan public sites for exactly these key formats, so assume it has already been copied.
- Roll the key now: Stripe Dashboard → Developers → API keys → Roll key.
- Move Stripe calls to a server route/edge function and keep the key in a server-only env var (no NEXT_PUBLIC_/VITE_ prefix).
- Remove the key from client code and any NEXT_PUBLIC_ / VITE_ variable, and keep it in a server-only env var.
- Check the provider's usage/audit log for activity you don't recognise.
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
criticalOpenAI API key exposed in client code
Show details ▾/assets/app.js · sk-pro…Key0 (64 chars)
OpenAI API key exposed in client code
Show details ▾A OpenAI API key is sitting in a file your site serves to every visitor, so anyone can copy it.
Critical. Blast radius: Your OpenAI account and bill: anyone can run models on your quota until you hit your spend limit, and read files/assistants stored in the project.
If this key is live (we matched its format; we did not use it): 1) an attacker opens your site, views the page source or JS bundle (/assets/app.js) and copies the key; 2) they use it from their own machine with the provider's normal API, outside your app and its limits; 3) they run large volumes of requests (or resell access) billed to you, and can read any files or assistants in that project. Bots scan public sites for exactly these key formats, so assume it has already been copied.
- Revoke the key at platform.openai.com/api-keys and create a new one.
- Remove the key from client code and any NEXT_PUBLIC_ / VITE_ variable, and keep it in a server-only env var.
- Check the provider's usage/audit log for activity you don't recognise.
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
criticalSupabase service_role key exposed
Show details ▾/assets/app.js · eyJhbG…xxxx (173 chars)
Supabase service_role key exposed
Show details ▾Your Supabase admin key (service_role / secret key) is in public JavaScript. It skips Row Level Security entirely.
Critical. Blast radius: Full database read/write/delete: every row in every table for all users, plus auth users and storage files. Your RLS policies do not apply to this key.
If this match is real (we matched a pattern; we did not test it), 1) An attacker copies the key from /assets/app.js; 2) they point the standard Supabase client (or plain HTTP requests) at your project URL using this key; 3) they can download every table, change any row (e.g. make themselves admin or edit balances) and delete data, and none of it is blocked by RLS.
- Rotate it now: Supabase → Project Settings → API (or API Keys) → roll the service_role/secret key. Removing it from code is not enough.
- Update the key only in server-side env vars (no NEXT_PUBLIC_ / VITE_ prefix); call admin operations only from server routes or edge functions.
- Review tables, auth users and storage for changes you didn't make; restore from backup if needed.
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
criticalTable "profiles" readable with the public anon key
Show details ▾your-project.supabase.co/rest/v1/profiles
Table "profiles" readable with the public anon key
Show details ▾Anyone can read the "profiles" table using only the public key your site ships, because Row Level Security isn't stopping signed-out reads.
Critical. Blast radius: Every row in profiles for all users, a table that usually holds sensitive data (names, emails and any other personal details stored per user). Read access confirmed for signed-out visitors; writes were not tested, so check INSERT/UPDATE/DELETE policies too.
1) An attacker opens your site and copies the Supabase URL and anon key from the JavaScript (they are public by design); 2) they request the profiles table through Supabase's REST API with that key, the same request your app makes; 3) because no policy limits the rows, they page through and download the whole table, then use it for account takeover attempts, phishing your users, or publishing the leak. We fetched at most one row to prove this and kept only yes/no.
- Enable RLS: alter table public.profiles enable row level security;
- Add an owner-only read policy, e.g. create policy "own rows" on public.profiles for select to authenticated using ((select auth.uid()) = user_id);
- Drop any using (true) policy for anon unless this table is meant to be fully public.
- Test with two accounts: user B must not read, update or delete user A's rows, and A must not be able to change a row's user_id (needs with check on UPDATE).
- Check write policies with the free policy checker: abbilabs.xyz/tools/supabase-policy-checker
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
criticalTable "orders" readable with the public anon key
Show details ▾your-project.supabase.co/rest/v1/orders
Table "orders" readable with the public anon key
Show details ▾Anyone can read the "orders" table using only the public key your site ships, because Row Level Security isn't stopping signed-out reads.
Critical. Blast radius: Every row in orders for all users, a table that usually holds sensitive data (purchase history, amounts, and any billing details stored with them). Read access confirmed for signed-out visitors; writes were not tested, so check INSERT/UPDATE/DELETE policies too.
1) An attacker opens your site and copies the Supabase URL and anon key from the JavaScript (they are public by design); 2) they request the orders table through Supabase's REST API with that key, the same request your app makes; 3) because no policy limits the rows, they page through and download the whole table, then use it for account takeover attempts, phishing your users, or publishing the leak. We fetched at most one row to prove this and kept only yes/no.
- Enable RLS: alter table public.orders enable row level security;
- Add an owner-only read policy, e.g. create policy "own rows" on public.orders for select to authenticated using ((select auth.uid()) = user_id);
- Drop any using (true) policy for anon unless this table is meant to be fully public.
- Test with two accounts: user B must not read, update or delete user A's rows, and A must not be able to change a row's user_id (needs with check on UPDATE).
- Check write policies with the free policy checker: abbilabs.xyz/tools/supabase-policy-checker
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
criticalEnvironment file exposed (/.env)
Show details ▾/.env
Environment file exposed (/.env)
Show details ▾Your /.env file is downloadable from your live site, and it contains environment variables (usually database URLs and API keys).
Critical. Blast radius: Every service whose credentials are in that file: often full database access, payment and email provider accounts, and third-party APIs.
1) An attacker requests /.env on your domain (automated scanners try this on every site); 2) they read the variable names and values; 3) they use those credentials directly, e.g. connecting to your database or calling Stripe as you.
- Rotate every secret in the file first, at each provider. Deleting the file does not stop anyone who already downloaded it.
- Remove the file from your public/static folder and deploy output.
- Block dotfiles at your host (e.g. a vercel.json redirect for /.env*).
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
highAWS access key ID exposed in client code
Show details ▾/assets/app.js · AKIAFA…1234 (20 chars)
AWS access key ID exposed in client code
Show details ▾A AWS access key is sitting in a file your site serves to every visitor, so anyone can copy it.
High. Blast radius: Whatever this IAM user can reach: commonly S3 buckets (read/write/delete files), and sometimes compute or other services that run up your AWS bill.
If this key is live (we matched its format; we did not use it): 1) an attacker opens your site, views the page source or JS bundle (/assets/app.js) and copies the key; 2) they use it from their own machine with the provider's normal API, outside your app and its limits; 3) an access key ID alone is not enough, but it is often shipped next to its secret; with both they list and download your buckets or launch resources billed to you. Bots scan public sites for exactly these key formats, so assume it has already been copied.
- Deactivate the key in AWS IAM and create a new one.
- Remove the key from client code and any NEXT_PUBLIC_ / VITE_ variable, and keep it in a server-only env var.
- Check the provider's usage/audit log for activity you don't recognise.
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
highGit repository exposed (/.git/HEAD)
Show details ▾/.git/HEAD
Git repository exposed (/.git/HEAD)
Show details ▾Your site serves its .git folder, so anyone can rebuild your source code and its full commit history.
High. Blast radius: Your whole codebase and every secret ever committed to it, including ones you later deleted.
1) An attacker fetches /.git/HEAD and sees it is served; 2) they use a common git-dumping tool to download the repository objects; 3) they search the history for keys and passwords, and study the code for other weaknesses.
- Rotate every secret ever committed to the repo (the history was public).
- Exclude .git from your deploy output, or block /.git at the web server.
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
mediumMissing Content-Security-Policy header
Show details ▾/
Missing Content-Security-Policy header
Show details ▾Your home page sends no Content-Security-Policy, so the browser will run any script that ends up on the page.
Medium. Blast radius: Every visitor's session on your site, but only if an attacker first finds a way to inject content (e.g. an XSS bug or a compromised third-party script).
If this match is real (we matched a pattern; we did not test it), if your app has an injection bug: 1) an attacker gets a script tag into a page (via a comment, profile field or compromised dependency); 2) with no CSP the browser runs it; 3) it acts as the logged-in user or sends their session data to the attacker. A CSP is the safety net that blocks step 2.
- Add a Content-Security-Policy header, starting with default-src 'self' and allowing only the origins you use (Supabase, Stripe, analytics).
- Set it in vercel.json headers or next.config headers(); try Content-Security-Policy-Report-Only first to avoid breakage.
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
mediumProduction source maps are public
Show details ▾/assets/app.js.map
Production source maps are public
Show details ▾Your production source maps are public, so anyone can read your original, unminified source code.
Medium. Blast radius: Your front-end source code and comments; anything sensitive in it (keys, internal URLs, admin routes) is exposed.
1) An attacker downloads the .map files (/assets/app.js.map); 2) browser dev tools rebuild your original files; 3) they read comments, hidden routes and any embedded keys to plan further attacks.
- Disable production browser source maps (Next.js: productionBrowserSourceMaps: false; Vite: build.sourcemap: false or 'hidden').
- Or block *.map at your CDN; upload maps privately to your error tracker instead.
- Check the exposed source for secrets and rotate any you find.
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
mediumPublic storage bucket "avatars"
Show details ▾storage/avatars
Public storage bucket "avatars"
Show details ▾The Supabase storage bucket "avatars" is public, so its files can be listed and downloaded without signing in.
Medium. Blast radius: Every file in the avatars bucket, for all users (e.g. avatars, uploads, documents, invoices if stored there).
1) An attacker reads your Supabase URL and anon key from your JavaScript; 2) they list the bucket's contents through the storage API; 3) they download every file, which is only harmless if the bucket really holds public assets.
- If it holds user uploads, set the bucket to private in Supabase → Storage.
- Serve files with short-lived signed URLs from your server.
- Add storage.objects RLS policies so users only reach their own folder.
- Severity stays medium for every public bucket because we don't open the files — prioritize by what you know is stored there.
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
lowClickjacking protection missing (X-Frame-Options / frame-ancestors)
Show details ▾/
Clickjacking protection missing (X-Frame-Options / frame-ancestors)
Show details ▾Any website can load yours inside an invisible frame because there's no X-Frame-Options or frame-ancestors rule.
Low. Blast radius: Signed-in users' one-click actions on your site (e.g. delete, confirm, change settings).
If this match is real (we matched a pattern; we did not test it), 1) An attacker builds a page that loads your site in a transparent iframe; 2) they place a decoy button over one of your real buttons; 3) a signed-in user clicks the decoy and actually performs the action on your site.
- Send X-Frame-Options: DENY, or Content-Security-Policy: frame-ancestors 'none'.
- How to verify: redeploy, then re-scan in Abbi Labs (abbilabs.xyz/dashboard). This finding should be gone.
Review what the AI changes before you deploy. Rotating a leaked key happens at the provider; the AI can't do that for you.
Want to know if your app has any of these?
The quick check takes about 30 seconds and needs no sign-up.
Scan my app free