Security checklist
Before your AI-built app goes live, check these ten things.
The checklist
1.No keys or passwords in the code
AI often pastes an API key straight into a file to get something working. Once it's in git, every copy and every export has it.
Check: Search the code for strings that look like keys (sk-, pk_live_, AKIA, ghp_, long random tokens) and for passwords in connection strings. Keys belong in environment variables.
On LazyFrog: The scan reports keys written into the code, with the file and line, and never shows the value. A push that contains one is refused.
2.No secret keys in what the browser downloads
Anything with a NEXT_PUBLIC_ or VITE_ prefix, or in a built bundle, is sent to every visitor. A secret key there is public.
Check: Only keys meant to be public (a publishable key, a site key) may reach the browser. Calls that need a secret key go through your server.
On LazyFrog: The scan reports secrets in built bundles and public files. Rotate a key that was exposed: moving it isn't enough.
3.Every route that changes data checks who is calling
AI writes the admin page and its API, but often forgets to protect the API itself. Anyone who finds the address can then delete or change data.
Check: For each POST, PUT, PATCH and DELETE handler: is the session or a signed webhook checked before anything changes? Hiding the button isn't protection.
On LazyFrog: The scan reports Next.js API routes that change something with no sign of an authentication check. Other frameworks: check by hand.
4.Queries take values as parameters, not built from strings
A query that pastes user input into the SQL text lets a visitor rewrite the query: read other people's data or delete a table.
Check: Look for SQL written with template strings, + or f-strings around user input. Use the driver's parameters ($1, ?) or an ORM's bound values.
On LazyFrog: The scan reports SQL built by interpolation or string joining, in JavaScript, TypeScript and Python.
5.User text is shown as text, not as HTML
Showing what a visitor typed as HTML lets them run scripts in other visitors' browsers.
Check: Look for dangerouslySetInnerHTML, innerHTML, v-html, {@html} and |safe. Show text as text, or sanitise it first.
On LazyFrog: The scan reports each of these when the value comes from a variable.
6.The database isn't open to the internet
Apps built on a hosted database often let the browser talk to it directly. With access rules off or too loose, anyone can read every table.
Check: If the browser reads the database (Supabase, Firebase), make sure row-level security or access rules are on for every table, and test them signed out.
On LazyFrog: Each project's PostgreSQL is reached only by its own app and by your AI through LazyFrog's tools, never directly from the internet. The scan doesn't check an outside database's rules.
7.Packages are pinned and free of known holes
AI adds packages freely and rarely updates them. Old versions can have published vulnerabilities.
Check: Commit the lockfile, run your package manager's audit, and update what it flags.
On LazyFrog: The scan checks the locked packages against published vulnerabilities and says which version fixes each one.
8.Public forms are limited and checked
A contact or sign-up form with no limits gets filled by bots, and one that trusts its input breaks in odd ways.
Check: Validate every field on the server, cap the length, and limit how often one visitor can send.
On LazyFrog: a check by hand; the scan doesn't look for this.
9.Errors don't show the inside of the app
A stack trace on the page tells an attacker your file paths, versions and sometimes queries.
Check: Make the live site show a plain error page and keep the details in the logs. Try a wrong address and a broken form.
On LazyFrog: Logs are cleaned of keys, tokens and card numbers before they're written.
10.There's a way back
A bad change or a deleted table happens to everyone. Without a copy, it's permanent.
Check: Make sure the database is backed up and that you have restored from a backup once.
On LazyFrog: Snapshots of the code, the database and the files, one before every risky change, and an earlier version back in seconds.
A real scan, before and after
Before: 6 findings
- High
sql-injectionapp/api/suggestions/[id]/route.ts:6SQL built by interpolating values into the query text
- High
sql-injectionapp/api/search/route.ts:6SQL built by joining strings
- High
xssapp/book-note.tsx:3HTML injected from a variable (dangerouslySetInnerHTML)
- High
secret-in-codelib/summary.ts:2A secret written into the code (it ends up in git and in exports)
- High
secret-in-clientpublic/checkout.js:2A secret in a file browsers download (built bundle or public file)
- Medium
missing-authapp/api/suggestions/[id]/route.ts:4DELETE handler with no sign of an authentication or authorisation check
After: 0 findings
We asked Codex, in the same chat: “Run a security scan on page-turners-check and fix everything it finds. Don't publish.” It took 20 steps in under three minutes, then scanned again:
- The search takes its value as a parameter, with a length limit.
- The open delete route is gone; deleting stays on the password-protected admin page.
- The book note is shown as text, not HTML.
- Both keys are out of the code: the summary reads its key from the environment on the server, and the browser file holds no secret.
- It reminded us to revoke both keys at their providers, since removing them from the code doesn't make them safe.
The keys were made up for the test and never worked. The second scan found 0 problems in 52 files. One of the six, SQL joined from a string that contained quotes, slipped past our scanner the first time; we fixed the scanner the same day, and the list above is what it reports now.
Run the scan on your app
Ask your AI to “scan my app for security problems”, or open the project's Security screen in your LazyFrog account. Each finding comes with a fix to give your AI. Importing an app from Lovable, Bolt or GitHub runs it once by itself. New to hosting an AI-built app? Start here.
Questions
- Are vibe-coded apps less secure?
- Not by nature, but AI-written code tends to repeat a few mistakes: keys in the code, routes nobody protected, queries built from strings. They're easy to find and easy to fix once you look.
- What does LazyFrog's security scan check?
- Keys and passwords in the code and in what the browser downloads, SQL built from strings, HTML from variables, Next.js API routes with no authentication check, vulnerable packages and accessibility. Each finding comes with a fix to give your AI.
- How do I run it?
- Ask your AI to scan the project, or open the Security screen of the project in your LazyFrog account. An import runs it once by itself.
- Does a clean scan mean the app is secure?
- No. It finds common mistakes in the code; it doesn't know what your app should allow. The items on this page without a scan note are checks by hand.