Security Holes to Check in a Lovable or Replit App Before Launch
By Waseem Ahmad — Full Stack Developer & AI Engineer ·
TL;DR
- AI coding tools generate code that works, not code that is safe. Authorization, rate limiting, and secrets management are rarely included unless you ask for them explicitly.
- The most common critical finding in Lovable apps is broken access control: Row Level Security is either disabled or contains a
using (true)policy that quietly re-opens the table to anonymous writes. - Secrets belong in environment variables on the server. Any key committed to a public repository must be rotated, because it survives in git history after you delete the file.
- Mass assignment lets a logged-in user send
{"role": "admin"}in a PATCH body and have it written to the database. It is invisible until someone tries it. - A pre-launch audit is not a one-time sweep: each new feature added to a Lovable or Replit app can reintroduce a vulnerability class that was clean the week before.
Large language models are trained to satisfy the functional request, not the threat model. The feature works on the first prompt, so it ships. Security controls are not in the training objective, so they do not appear in the output.
The tools — Lovable, Bolt, Cursor, Replit, v0, Claude Code — have collapsed the time from idea to deployed URL from weeks to hours. The security infrastructure has not kept pace. The result is a category of applications that pass every demo but carry structural holes that a basic code review would catch.
What follows is a description of what a vibe code security audit actually covers: the four vulnerability classes that come up most consistently, why automated scanning alone is not sufficient, and where the work gets hard. For context on how security requirements compound when user data is sensitive, the PSI Nest engagement covers the additional controls that apply when a healthcare platform stores protected information. For broader hardening work, see the vibe code rescue service.
Why Does AI-Generated Code Have These Specific Holes?
Three reasons. First, training data is biased toward functionality over security — models see far more "login example" than "secure login example." Second, AI optimizes for what was asked; security is rarely the prompt. Third, AI lacks awareness of the wider attack surface, so it secures one route while leaving the sibling open.
The vulnerabilities found in Lovable are not unique to Lovable. Bolt.new, Replit, and other vibe coding tools share many of the same weaknesses. The problem is not any single platform — it is the fundamental approach of generating code without security context.
Replit has moved to address some of this: the Replit Security Agent, shipped April 21, 2026, scans for vulnerabilities and audits dependencies before publish, using Semgrep and HoundDog.ai in a hybrid approach to reduce false positives, and maps routes and APIs to check for SQL injection, XSS, and request forgery. Automated tooling catches a class of obvious issues. It does not catch business-logic authorization errors, which is where the serious risk lives.
The Four Vulnerability Classes an Audit Checks
1. Authorization vs. Authentication
These are not the same thing, and vibe-coded apps routinely conflate them. Authentication proves who you are. Authorization controls what you can access. AI tools handle authentication reasonably — they wire up Supabase Auth or a JWT library and the login form works. Authorization is where the gap opens.
AI models put security controls on the client side: auth checks in JavaScript, authorization logic in the browser. Both are bypassable in seconds. Any check that lives only in the frontend can be stripped by editing the page or sending a raw HTTP request. The server must enforce who can read or write each resource, independent of what the UI renders.
For Supabase-backed apps, the enforcement layer is Row Level Security. Every Lovable app uses Supabase, which exposes a public REST API. Without RLS, that API gives anyone who knows the Supabase URL full read and write access to the database. The audit checks that RLS is enabled on every table, that no policy body contains using (true) where it should not, and that ownership checks exist on every CRUD operation. Lovable's AI creates new tables as features are added but does not consistently add RLS policies to each new table. An app that starts secure can become vulnerable after a single new feature ships.
Real consequences have followed. Security firm Wiz disclosed that Moltbook, a social platform, shipped with its Supabase API key embedded in client-side JavaScript and no row-level security; 1.5 million API tokens and 35,000 user emails were exposed within days of launch.
2. Client-Side Secrets
Every key that ships to the browser is effectively public. AI models generate code that works, and the fastest path to working is often embedding API keys, database passwords, or JWT secrets directly in source files. The audit checks every environment variable reference in client-side bundles, every fetch() call that includes an authorization header built from a frontend variable, and every third-party integration where the secret key is used in browser code rather than proxied through a server route.
Git history is a separate problem. The vibe coding workflow amplifies this risk: code is generated quickly, tested locally, and pushed to a public repository before anyone thinks to move secrets into environment variables. By the time the push happens, the secret is already in git history. Removing the file in a later commit does not remove the key from history. Rotation is the only fix.
GitGuardian's State of Secrets Sprawl report found that almost 70% of exposed credentials validated as legitimate in 2022 remained valid through January 2025. 64% were still exposed and unrevoked as of January 2026. Exposed secrets stay exploitable for a long time because rotating them requires coordination that teams defer.
The Supabase-specific distinction: the Supabase URL and anon key ship to the browser by design. That is not the vulnerability on its own. The vulnerability is shipping the anon key to the browser without RLS enforced on every table, because the anon key is then effectively a read/write key for the whole database. The service role key is different — it bypasses RLS entirely and must never appear in client-side code.
3. Missing Rate Limits
AI tools create vulnerable code because rate limiting is not required for functionality. When you ask for a login endpoint, AI generates code that authenticates users — that is the complete request. Security features like rate limiting are "extra."
Auth endpoints, password reset flows, and expensive queries ship without rate limits. This enables credential stuffing, brute force, and resource exhaustion. Approximately 80% of vibe-coded apps lack rate limiting on at least one auth endpoint (VibeEval, 2026).
The audit checks three endpoint categories: authentication routes (login, password reset, magic link), resource-intensive operations (report generation, bulk exports, LLM calls billed per token), and write endpoints that could be spammed for fraud. The fix is not complicated — five requests per minute per IP for auth endpoints, 100 per minute for general API traffic, using express-rate-limit or upstream Cloudflare rules — but it must be applied deliberately. Rate limiting is classified as CWE-799 and appears in the OWASP API Security Top 10 as API4:2023: Unrestricted Resource Consumption.
4. Mass Assignment
Mass assignment happens when you pass req.body directly to your database layer, allowing an attacker to set fields they should not control — for example, isAdmin: true. AI-generated CRUD endpoints do this routinely because the shortest working code is db.users.update(req.user.id, req.body).
User update endpoints accept arbitrary fields, including role or permissions. A logged-in user can send PATCH /api/users/me {"role": "admin"} and escalate their privileges. The audit tests this by reading the fields returned by a GET endpoint and then sending each one back in a PATCH or PUT body to see which ones the server accepts without error.
The fix is an allowlist. The principles that prevent mass assignment: never expose the entity directly to the HTTP surface, define a separate DTO or schema for each endpoint, and use an allowlist rather than a blocklist. A safe default means "what is allowed," not "what is forbidden." Identity information must come from the token, never from the client. Fields like body.user_id, body.owner_id, and body.tenant_id must never be accepted; these values come from the session or JWT.
What Does Automated Tooling Actually Cover?
Static analysis and dependency scanners are worth running. Semgrep catches hardcoded secret patterns. npm audit surfaces known CVEs. These are table stakes, not the audit itself.
An effective AI code security audit combines automated scanning — SAST for code-level flaws, SCA for dependency vulnerabilities, DAST for runtime issues — with manual expert review. Manual review is critical because automated tools miss business logic flaws, authentication design errors, and infrastructure misconfigurations.
A secondary issue automated tools miss entirely is dependency confusion. AI models occasionally reference packages that do not exist on npm or PyPI. The audit checks that every import resolves to a real, actively maintained package and was not silently substituted by a similarly named malicious one.
For applications handling health data or financial records, the scope expands. The HIPAA-compliant healthcare software post covers the additional controls required when protected health information is in scope. The four checks above are a floor, not a ceiling. For multi-tenant SaaS, tenant isolation at the database layer directly interacts with the authorization checks described here — the multi-tenant SaaS architecture post covers that design.
Audit Sequence at a Glance
| Check | Method | Pass Condition | Common Failure |
|---|---|---|---|
| RLS on every Supabase table | Supabase dashboard + SQL query | RLS enabled; no unintentional using (true) |
New table added by AI without any policy |
| Server-side authorization | Code review + Burp Suite intercept | Every route checks ownership from JWT, not request body | UI hides the button; API has no check |
| Secrets in client bundle | Built JS grep + git log -S "sk_" |
No keys in bundle; no secret patterns in commit history | OpenAI or Stripe key in src/config.ts |
| Rate limiting on auth routes | Manual request burst + code review | 429 returned after configured threshold per IP | Login endpoint accepts unlimited POST requests |
| Mass assignment on write endpoints | Inject extra fields into PATCH body via Burp | Server returns 400 or ignores unknown fields without writing | req.body passed directly to ORM update call |
| Dependency integrity | npm audit + manual package name check |
No high/critical CVEs; all packages resolve to real registry entries | Hallucinated package name squatted by attacker |
Sequencing matters. Authorization checks come first because a working auth bypass makes other controls largely redundant. Secrets come before rate limits because an exposed key enables automated abuse that rate limits slow but do not prevent on their own.
FAQ
Does Replit's built-in Security Agent replace a manual audit?
No. The Replit Security Agent scans for vulnerabilities before publish, using Semgrep and HoundDog.ai, and maps routes and APIs to check for SQL injection, XSS, and request forgery. That covers a useful subset of static and dependency issues. It does not test whether your business logic allows user A to read user B's data, whether a PATCH endpoint accepts privilege-escalating fields, or whether rate limits are correctly scoped per endpoint type. Those require a human actively trying to break the app.
My app only has a few users right now. Is an audit still necessary before launch?
The danger comes when non-technical users treat these tools as complete solutions. When you vibe code an entire SaaS application and deploy it without a single line of code review, you are essentially publishing a vulnerable application to the internet and hoping nobody attacks it. The size of the user base does not determine when an attacker finds the URL. The Moltbook exposure happened within days of launch.
If I add a new feature after the audit, does the audit stay valid?
Not automatically. Lovable's AI creates new tables as features are added but does not consistently add RLS policies, so a project that starts secure can become vulnerable after adding one feature. Any change that touches the database schema, adds an API route, or handles a new file type warrants a targeted re-check of the four categories above.
Hire me for similar projects
Looking for a developer who can build what you just read about? Let's talk.
Get in Touch