Security issues in AI-generated apps: what to check and how to fix them
6 min read
On this page
AI app builders such as Lovable, Bolt, v0, Replit and Cursor can turn a description into a working app in an afternoon. What they produce usually looks finished, but "it works when I click through it" is not the same as "a stranger cannot read my customers' data". The most common gaps are predictable, and many of them can be spotted by a non-technical founder in under an hour. This page walks through them in order of risk.
Why AI-built apps tend to have the same gaps
AI tools optimise for the feature you asked for. When you say "add a dashboard that shows orders", the shortest path to a working dashboard is often to fetch every order from the database straight into the browser and filter it there. It works in the demo. It also means any visitor who opens the browser's developer tools can see every order.
The same pattern repeats: a key pasted into the frontend so an API call works, a table created without access rules so a query stops failing, an API route left open because a login check broke something. It just needs to be found and fixed before real users arrive.
The six issues to look for
1. Secret keys in the client bundle
Anything the browser downloads, anyone can read. In Vite projects, environment variables that start with VITE_ are copied into the JavaScript sent to the browser. In Next.js, the same happens with NEXT_PUBLIC_. If a Stripe secret key, an OpenAI key, or a Supabase service role key has one of those prefixes, it is public.
How to check: open your live site, open developer tools (F12), go to the Sources or Network tab, and search the JavaScript files for sk_live, sk_test, service_role, secret and api_key. You can also paste your .env file or config into the secret leak scanner, which runs entirely in your browser and flags common key formats.
2. Database tables without Row Level Security
Many AI-built apps use Supabase. Supabase exposes your database through an API that the browser calls directly, and Row Level Security (RLS) is the only thing deciding who can read or change each row. If RLS is off on a table, anyone holding the public key can read the whole table. If a policy says using (true), the effect is much the same.
How to check: in the Supabase dashboard, open the table editor and look for tables marked as unrestricted or without RLS. Then export your policy SQL and paste it into the Supabase RLS checker, which highlights open policies and missing with check clauses. If you find problems here, the Supabase auth and RLS page goes deeper.
3. Unvalidated input
AI-generated forms often accept whatever is typed. If a server function builds a database query, a file path or an HTML snippet from raw input, an attacker can shape that input to do something you never intended. Validation must also happen on the server, because browser-only checks can be skipped by calling the API directly.
How to check: try entering very long text, HTML such as <b>test</b>, negative prices or quantities, and other users' IDs into forms and URLs. If the app accepts and displays them unchanged, input handling needs work.
4. API routes with no login or ownership check
Server routes and edge functions are often generated with the happy path in mind: they assume the caller is logged in and owns the record. Two separate checks are needed. Is there a logged-in user at all? And does this user own the thing they are asking for? Missing the second check is very common, and it lets one customer read or edit another's records by changing an ID in the request.
How to check: log in as user A, note the ID of something they own, then log in as user B in a private window and try to open or edit that same ID. If it works, the route is missing an ownership check.
5. Permissive CORS settings
CORS tells browsers which other websites may call your API. A setting that echoes back any origin while allowing cookies lets a malicious site make requests using your visitor's session. CORS also does nothing to stop someone calling your API from a script, so it never replaces proper auth checks.
How to check: search your server code for Access-Control-Allow-Origin and cors(. A wildcard on a public, read-only API can be fine; a wildcard or an echoed origin on routes that use logins deserves a closer look.
6. Secrets committed to git
If a .env file was ever committed, the keys stay in the repository history even after the file is deleted. Public repositories are scanned by automated bots looking for exactly this.
How to check: run the repo health check on a public repository to see whether environment or secrets files are present. For any key that was ever committed, assume it is exposed: rotate it in the provider's dashboard, then update the new value wherever the app is hosted.
What to do in the next 24 hours
You do not need to understand every detail to reduce the risk quickly:
- Rotate any key you found in the browser bundle or in git history.
- Turn on RLS for every Supabase table that holds user data, even before policies are perfect (an RLS-enabled table with no policies blocks public access).
- Check usage dashboards for Stripe, your AI provider and your email service for activity you do not recognise.
- Make sure you, not a contractor, own the hosting, database, domain and code accounts.
- Write down what you found, with screenshots that do not show the keys themselves.
What a rescue developer will typically check first
A developer taking over a security clean-up usually starts with an inventory rather than fixes. Expect them to:
- List every secret the app uses, where each one is stored, and whether it ever reached the browser or the repository.
- Read every RLS policy and storage bucket rule, then test them with two real test accounts rather than trusting the code.
- Walk each API route and server function asking "who can call this, and what stops them reaching someone else's data?"
- Check the auth flow end to end: sign-up, email confirmation, password reset, session expiry and logout.
- Review dependencies and hosting settings, including CORS, environment variables per environment, and whether errors leak stack traces to users.
They will likely ask for collaborator access to your repository, database and hosting rather than your passwords. The guide on giving a developer access without sharing passwords explains how to set that up for the common platforms. For a wider view of what "ready for real users" means, see the prototype to production checklist.
Get a developer to finish the job
Security fixes in an AI-built app are usually a series of small, careful changes that each need testing. If you would rather hand that to someone who does it regularly, post your takeover on TakeoverWork. Posting is free. Describe the stack, what you have already checked on this page, and what worries you most. Do not paste keys, passwords or customer data into the listing.
TakeoverWork connects you with developers and agencies who take on started projects. It does not check or employ them, and it never handles project payments, so agree the scope and price directly with whoever you choose. The production readiness checklist is a useful shared list to work from once you have picked someone.
Live matching takeovers
No matching takeovers are open right now
New projects are posted regularly. Browse every open takeover, or post your own project free.
Browse all takeoversFrequently asked questions
Is the Supabase anon key in my frontend a security problem?
Not by itself. The anon or publishable key is designed to be public, and Row Level Security is what protects your data. It becomes a problem when RLS is off or when policies allow everyone to read or change every row. The service role or secret key is different and must never reach the browser.
I deleted the .env file from my repository. Am I safe now?
No. Git keeps every earlier version of every file, so the key is still in the history and anyone with access to the repository can find it. Rotate the key in the provider's dashboard first, then decide whether to clean the history.
Can I ask the AI builder to fix the security issues itself?
You can ask, and it may fix some of them, but AI tools often report a fix without checking the result. After any change, test it yourself: log in as a second user and try to read the first user's data, and search the built JavaScript for secret keys.
How urgent is a leaked secret key?
Treat it as urgent. Keys for payment, email or AI APIs can be used to run up charges or send messages in your name within hours of being found. Rotate the key straight away, then look at usage logs for anything you did not do.
Should I pause my app while it is being fixed?
If real users or payments are involved and you have confirmed that private data can be read by strangers, pausing sign-ups or taking the app offline briefly is often the safer choice. A developer can help you decide based on what the data actually contains.
Stuck with a half-built app?
Post your project free. Developers who finish and rescue projects can send you an interest note, and you decide who to talk to. You agree scope and payment directly with them.
Free tools that help
Related guides
From vibe-coded prototype to production: the 25-point checklist
Your AI-built prototype works in the demo. These 25 checks, grouped into ten areas, cover what usually needs attention before real users and real money arrive.
ReadLovable, Bolt and v0 apps: the most common reasons they break in production
AI app builders are excellent for prototypes. These are the gaps that usually appear when a prototype meets real users, real data and a real domain, and how to close them.
ReadHow to give a developer access without sharing passwords
Use team invites and limited roles instead of shared passwords, service by service, and know exactly how to remove access and rotate keys when the work ends.
ReadRelated problems
Supabase auth or RLS broken? How to find the cause
Supabase auth and RLS problems show up as login loops, missing emails, empty pages or data leaks. Most come from a handful of settings and policy patterns.
ReadLovable app not working? How to find what broke and get it fixed
Most Lovable apps that break do so for a short list of reasons: auth settings, database policies, keys, deploys, edge functions or payments. Here is how to narrow it down.
ReadBolt app stuck? How to get your project moving again
A stuck Bolt project usually means the AI has lost track of a large codebase, the build is broken, or the app only works inside the browser preview.
Read