Use Claude to Audit Your Lovable App: Security, Speed and Access
Your Lovable app works, but is it safe, fast and usable for everyone? Here is how I use Claude Code to review AI-built apps for Supabase RLS gaps, exposed keys, slow pages and accessibility problems, with prompts you can copy.

This post is for intermediate builders. You have an app built with Lovable, Bolt or another AI builder. It works, maybe it has real users, and you have a quiet worry that something is wrong underneath. You are right to worry a little. AI builders are very good at making things work and less consistent at making them safe.
A second AI looking at the code with a different job ("find problems" instead of "make it work") catches a lot. Here is the audit process I use with Claude Code, in the order I run it.
Set up: get the code where Claude can read it
- Connect your Lovable project to GitHub if you have not already.
- Clone the repo to your computer, or open it in Claude Code on the web at claude.ai/code, which works directly from GitHub.
- Start Claude Code in plan mode (press Shift+Tab until the status line says plan mode, or run
claude --permission-mode plan). Plan mode lets Claude read everything but change nothing. For an audit, that is exactly what you want.
Run each audit below in its own session. Type /clear between them. A security review and an accessibility review in the same long session will both be worse.
Audit 1: Exposed keys and secrets
Start here because it is the fastest and the most damaging when wrong.
Supabase now has two kinds of keys. The publishable key (or the legacy anon key) is meant to be in your front end. It is safe because your row level security policies decide what it can do. The secret key (or the legacy service_role key) bypasses RLS completely and must never be in browser code, a shipped app or your git history. The Supabase API keys guide explains the difference.
The same rule applies to Stripe secret keys, OpenAI or Anthropic API keys, email provider keys and anything else that costs money or grants access.
Audit this codebase for exposed secrets. Do not change any files.
1. Search all front-end code (src/ and anything bundled to the
browser) for API keys, tokens and passwords. Flag anything
that is not a Supabase publishable or anon key or a Stripe
publishable key.
2. Check every environment variable with a public prefix
(VITE_, NEXT_PUBLIC_, etc). List each one and say whether
it is safe to expose.
3. Check git history for secrets that were committed and later
removed: run git log -p and search for key patterns.
4. List every place the code calls a paid third-party API and
say whether that call happens in the browser or on a server.
Report findings as a table: file, line, what it is, severity,
recommended fix.
If a secret shows up anywhere, including old commits, rotate it in the provider's dashboard. Deleting it from the code does not help once it has been pushed.
Audit 2: Supabase row level security
This is where I find the most real problems in AI-built apps. Common ones: a table with RLS turned off, a policy that lets any logged-in user read every row, or an insert policy that does not check the user is inserting their own data.
Review the Supabase database security for this app. Do not
change any files.
1. Read every file in supabase/migrations in order and build a
list of all tables in the public schema.
2. For each table, tell me: is RLS enabled, and what are the
select, insert, update and delete policies in plain English?
3. Flag any table where:
- RLS is not enabled
- a policy uses "true" or allows all authenticated users
when the data belongs to one user or one team
- insert or update does not check ownership (auth.uid())
- a column like role, is_admin, plan or credits can be
changed by the user it belongs to
4. Check storage buckets and their policies the same way.
5. Check every edge function: does it use the secret key, and
if so, does it verify who the caller is before acting?
For each problem, explain the attack in one sentence ("Any
logged-in user could read every other user's invoices") and
propose the policy fix as SQL. Do not apply it.
Then verify by hand. Create two test accounts. Log in as user A and try to load user B's data by changing an ID in the URL or the request. Claude's review tells you where to look. Your own test tells you if it is actually fixed.
If your migrations folder is missing or out of date (common with apps built visually), export the current policies from the Supabase dashboard or SQL editor and paste them into the session.
Audit 3: Performance
Slow apps lose users quietly. AI builders tend to fetch too much data, fetch it too often and ship large images.
Review this app for performance problems. Do not change files.
Look for:
- Database queries that select all columns or all rows when the
page only shows a few
- Queries inside loops, or one query per list item
- Columns used in filters or joins that probably need an index
(list them with the query that uses them)
- Data refetched on every render or every page visit with no
caching
- Large images without width, height or lazy loading
- Heavy libraries imported for one small feature
- Pages that load everything up front instead of on demand
Rank findings by likely impact on what a real user feels, and
for each one estimate how hard the fix is (small, medium, large).
Fix the top two or three, measure again, and stop. Performance work has no natural end, and most small apps need only the obvious fixes.
Audit 4: Accessibility
Accessibility is about whether people using keyboards, screen readers or zoom can use your app at all. It also tends to improve the experience for everyone.
Review the front end for accessibility problems against WCAG
2.1 AA. Do not change files.
Check:
- Every form input has a visible label connected to it
- Buttons and links have clear text (not just an icon)
- Images have useful alt text, or empty alt if decorative
- Color contrast of text against its background, especially
gray text, placeholder text and text on colored buttons
- Everything clickable can be reached and used with the
keyboard, with a visible focus outline
- Modals trap focus and close with Escape
- Error messages are announced, not only shown in red
- Headings go in order on each page
List each issue with the component file, what a user would
experience, and the fix.
Then do a two-minute manual check: unplug your mouse and try to sign up and complete the main task with only the Tab, Enter and Escape keys. If you get stuck, so will some of your users.
Fixing what you find
Do not ask Claude to fix everything at once. Here is the loop:
- Commit your current code so you have a clean save point.
- Pick one finding. Switch out of plan mode and ask Claude to fix only that one, and to show you how it tested the fix.
- Review the change, test it yourself, commit.
- Repeat.
For database policy changes, have Claude write a new migration file rather than editing old ones, and apply it to a test project before production if you can.
Be honest about what this replaces
A Claude audit is a very good first pass. It is not a penetration test, and it can miss things or flag problems that are not real. Ask it to explain any finding you do not understand, and push back when something sounds wrong. A reviewer told to find problems will usually find some, so focus on the ones that affect real data or real users. If your app handles health, financial or children's data, pay a human security professional as well.
It also helps to repeat the audit after big changes. Once you have a clean baseline, the built-in /code-review command in Claude Code reviews your pending changes for bugs before you commit them.
Where to go next
If you are new to RLS, the free Intro to Vibe Coding course on the Courses page covers the basics. The recipes include security checks in every build spec, so new features start out safe.
What would have made it better?