Skip to main content

Cardinal Stacks blog

Lovable App Security: 7 Fixes Before Production

Seven Lovable app security gaps show up on almost every audit Cardinal Stacks runs: weak auth defaults, missing Supabase Row Level Security, API keys in git, no spend ceiling on LLM endpoints, console-only error handling, manual deploys with no rollback, and PII flowing to LLMs unredacted. This is the CTO's read on what to find and how to fix each one before you onboard paying users.

Cardinal Stacks7 min read

01 · Auth: bcrypt cost factor and session expiry

The risk. Default Lovable auth scaffolds often ship with low password-hash work factors and sessions that never expire. A stolen laptop or a leaked database dump becomes a long-lived account takeover instead of a window that closes on its own.

What to look for. Open your auth config and find the bcrypt cost factor. If it is below 10, or if the value is not set at all and the library default applies, that is the gap. Then check your session table or JWT payload. If you see a session created six months ago that is still valid, expiry was never configured.

How to fix it. Set bcrypt to a cost factor of 12 in 2026: high enough to slow offline cracking, low enough to keep login latency under 200ms on commodity hardware. Set session idle expiry to 14 days and absolute expiry to 30 days for a consumer app. For anything touching payment or PII, drop those to 24 hours idle and 7 days absolute. Add a server-side revocation table so a password reset or a logout actually kills active sessions.

02 · Row Level Security on every Supabase table

The risk. Supabase is the default backend on most Lovable builds, and Row Level Security is off by default on every table you create. Any user with a valid anon key (which ships in your client bundle) can read and often write every row in every public table. This is the single most common path to PII exposure we see.

What to look for. Open the Supabase dashboard, go to Authentication then Policies, and scan the table list. If RLS is disabled on any table that holds user data, billing records, or messages, that is a bug. Then check the policies that do exist.

A policy of true with no auth.uid() filter is the same as no policy at all.

How to fix it. Enable RLS on every table without exception. Write per-table policies that filter on auth.uid() = user_id for owner-scoped tables, and explicit role checks for admin surfaces. Test with the Supabase SQL editor under the anon role before you trust the result. Audits of vibe-coded apps routinely find significant data-exposure vulnerabilities shipping before there are any real users on the system — RLS misconfiguration is the bulk of that number.

03 · API keys and secrets committed to git

The risk. Lovable scaffolds frequently inline API keys directly into source files: OpenAI, Stripe, Supabase service role, SendGrid. Once a secret is in git history, rotating it later does not undo the leak. Public repos get scraped within minutes; private repos get exposed the day they go public, or the day a contractor forks them.

What to look for. Run git log -p | grep -iE "sk-|api_key|secret|service_role" against your repo. Any match is a problem, even if the key looks rotated. Then check your client bundle: curl your production JS bundle and grep for the same patterns. Secrets baked into the build are visible to every visitor.

How to fix it. Move every secret to environment variables, scoped per environment (preview, staging, production). Rotate every key that ever touched git, even briefly. Add a pre-commit hook with gitleaks or trufflehog so a new secret cannot get committed by accident. For keys that need to reach the browser, use a server-side proxy. Never ship a write-capable key in client code.

04 · No spend ceiling on OpenAI or LLM endpoints

The risk. A chat endpoint or generation feature with no spend cap is a four-figure invoice waiting for a bad weekend. One scraper, one adversarial user with a script, one viral post: any of them can run your monthly OpenAI bill into five figures before you notice on Monday morning.

What to look for. Open the OpenAI dashboard and check Usage limits. If the hard cap is not set, or is set at the default account ceiling, you have no spend ceiling. Then audit your own code: any LLM call triggered by user input without a per-user rate limit, a per-request token cap, or input length validation is a cost vector.

How to fix it. Set a hard monthly spend cap in the OpenAI dashboard at a number that would hurt but not bankrupt you. For most early-stage apps that is $200 to $500. Add a per-user daily rate limit at the application layer (10 to 50 requests is a reasonable ceiling for a free tier). Cap max_tokens on every call. Validate input length before it hits the API. Log token usage per user so you can detect abuse before the bill arrives.

05 · No error monitoring beyond console.log

The risk. If your only error reporting is console.log, you learn about outages from customer email. By the time the third user has written in, the bug has been in production for hours, the data is already wrong, and you have no stack trace to work from.

What to look for. Search your codebase for console.log and console.error calls in catch blocks. If that is the only thing happening there, the error never leaves the browser. Then check your alerting: do you have any channel (email, Slack, phone) that pings you when production throws an unhandled exception? If the answer is no, your monitoring is your users.

How to fix it. Wire Sentry into both the client and the server with environment-scoped DSNs. Configure release tracking so a stack trace ties back to the exact deploy. Set up alerts on new issue types and on error rate spikes, not on every exception, which trains you to ignore the channel. Send alerts to a channel you already read, not a dashboard you have to remember to open.

06 · Manual deploys with no rollback

The risk. A manual deploy with no preview environment, no CI gate, and no rollback button means every push to production is a coin flip. A bad merge takes the site down with no fast path back to the last working version. This compounds the moment you have paying users: the same outage now costs revenue and trust.

What to look for. Check your deploy history. If you cannot point at a specific commit hash for the version currently in production, deploys are not reproducible. Check your CI: does the main branch require tests to pass before merge? Check your hosting platform: is there a rollback button, and have you ever used it? A button you have never tested is a button that does not exist.

How to fix it. Set up a CI gate on the main branch: at minimum a typecheck and a build step. Configure preview environments on every pull request so you can click around the change before merging. Use a host with one-click rollback (Vercel, Netlify, Railway all support this) and rehearse the rollback once on a Friday afternoon so it is muscle memory the day you need it. If this is the gap that worries you most, the full Vibe Rescue deploy surface covers the deploy pipeline end-to-end as one of its seven audited surfaces.

07 · PII flowing to LLMs unredacted

The risk. When a user types their name, email, phone, address, or medical detail into a chat interface and that text goes straight to OpenAI or Anthropic, you have just sent regulated data to a third party, often without a Business Associate Agreement, often without a data processing addendum, and often without your user knowing. In healthcare or financial apps this is a direct compliance failure. In any app it is a privacy gap your users will not appreciate when they find out.

What to look for. Trace any user-input field that feeds an LLM call. If the raw input string hits the OpenAI or Anthropic API without a redaction step in between, PII is leaving your perimeter. Check your logs too: prompt logs that store raw user input become a secondary PII store with the same exposure surface as your database.

How to fix it. Run user input through a redaction step before it reaches any external LLM. Cardinal uses Redactor, our in-house privacy guard, on every engagement that touches user data. It tokenizes names, emails, phone numbers, addresses, account numbers, and clinical identifiers before the prompt leaves your infrastructure, then re-hydrates the response on the way back. Whatever you use, the principle is the same: PII never reaches the third party, and your prompt logs never store the raw input. For apps under HIPAA, see our HIPAA software development notes. The BAA gap is not optional there.

What to do next

The seven items above are the recurring Lovable app security set. They are not theoretical and they are not exotic. These same gaps show up on almost every Lovable audit Cardinal runs, on apps whose screens and product logic are otherwise fine. The order roughly tracks blast radius: auth and RLS first because they expose user data directly, secrets and LLM spend next because they leak money fast, observability and deploys after that, PII redaction last because it sits on top of the rest. Work through all seven and you have a secure Lovable app at the layer underneath the screens.

If you want a second set of eyes on your own build, you can Get a free written audit of your Lovable app. Cardinal returns a written intake within two business days with a flat number and a list of must-fix items, no obligation to proceed. If the audit comes back clean, you keep the report at no cost and we tell you so.

Frequently asked questions

Is Lovable secure by default?
No. Lovable scaffolds ship with sensible defaults for some surfaces and unsafe defaults for others: Supabase Row Level Security is off by default on every new table, bcrypt cost factors are often left at the library minimum, and API keys are frequently inlined into source files. The framework is not insecure on purpose; it is optimized for shipping a working screen, not for production-grade defaults on the layer underneath.
Can I keep using Lovable after fixing these issues?
Yes. Every fix in this checklist is compatible with continued Lovable development. The hardening lives in config files, environment variables, Supabase policies, and a thin layer of server-side code around your LLM calls, none of which prevent Lovable from opening, editing, or extending the project. Cardinal's Vibe Rescue is specifically designed to merge hardened changes back into a codebase your editor of choice can still drive.
How long does it take to fix all 7?
For a senior engineer working full-time on a single app, the seven items take roughly 6 to 10 working days end-to-end. The Supabase RLS audit and the secret rotation are the slowest pieces because they require reviewing every table and every key the app has ever used. As a benchmark, Cardinal's Vibe Rescue ships the full hardened version in 14 calendar days at $4,800 flat, which includes deploy pipeline work and a screen-share handoff on top of the seven surfaces.
What's the most common Lovable security gap Cardinal sees?
Row Level Security disabled on Supabase tables holding user data. It shows up in well over half the audits we run. The gap is invisible in the Lovable editor (the app works exactly the same whether RLS is on or off), but the moment a single authenticated user runs a crafted query against the anon key, every row in every public table is readable. Industry audits of vibe-coded apps routinely flag data-exposure vulnerabilities, and this single misconfiguration is the bulk of what they're finding.
Next step

Free 48-hr audit. Written quote in two business days.

Same team, same flat-fee posture, same operating stack on every engagement. Email the repo or zip the project and the written audit lands in your inbox inside two business days.