LOVABLE TECH STACK & SECURITY ARCHITECTURE EXPLAINED (2026)
Lovable apps almost always mean React + Supabase + Vite. That stack is fine — until RLS is missing, the anon key is treated as a secret, or Edge Functions leak service_role.
SCAN YOUR LOVABLE STACK NOW
Paste your Lovable deploy URL — we fingerprint Supabase, test RLS, and hunt keys that should never ship to the browser.
Lovable’s Core Tech Stack
Every Lovable app ships with the same foundational stack. The frontend is a React single-page application scaffolded with Vite, styled with Tailwind CSS, and built using shadcn/ui components. Routing is handled by React Router. TypeScript is the default language.
That consistency is a product feature and a security property: auditors can learn one architecture and reuse the same probes across clients. It is also why mass scanners work. Understanding the stack is not academic — it is how you know where authorization must live (Postgres) when the framework never inserts a traditional backend.
The backend is entirely Supabase. This means PostgreSQL for the database, Supabase Auth for identity, Supabase Storage for file uploads, Edge Functions (Deno-based) for serverless logic, and Realtime for WebSocket subscriptions. There is no separate Express or Next.js server – Supabase is the entire backend layer.
Deployment happens through Lovable’s managed infrastructure. Apps get an automatic subdomain (project-name.lovable.app), HTTPS via Let’s Encrypt, and CDN-backed static asset delivery. Custom domains can be configured in the project settings.
Understanding this stack matters for security because every security boundary is either a Supabase feature or missing. There is no hidden API gateway to save you.
Layer map: where controls live
| Layer | Technology | Primary security control |
|---|---|---|
| UI | React + Vite + shadcn | XSS hygiene, no secrets in client state |
| Client data access | @supabase/supabase-js |
Anon key + user JWT only |
| Auth | Supabase Auth | Email confirm, password policy, OAuth redirect URLs |
| Authorization | Postgres RLS | Policies on every table |
| Files | Supabase Storage | Storage policies / private buckets |
| Server logic | Edge Functions (Deno) | JWT verify, no service_role in client |
| Hosting | Lovable CDN / custom domain | Headers, HTTPS, no public source maps |
If RLS is wrong, nothing above the database can fully compensate — the browser talks to PostgREST directly.
Authentication & Authorization Architecture
Supabase Auth handles authentication. It supports email/password, magic links, phone OTP, and third-party OAuth providers (Google, GitHub, Apple, Discord). On successful login, Supabase issues a JWT containing the user’s ID and role. This token is stored client-side and sent with every request.
Authorization is enforced through PostgreSQL Row Level Security (RLS). RLS policies are SQL expressions that run on every database query, filtering rows based on the authenticated user’s JWT claims. For example, a policy like auth.uid() = user_id ensures users can only access their own records.
Lovable exposes two Supabase keys in the frontend: the anon_key (public, safe to expose if RLS is enabled) and the project URL. The service_role key must never appear in client code – it bypasses all RLS policies and grants full database access. This is the single most critical secret in any Lovable app.
Auth settings that AI often leaves weak
- Email confirmation disabled → disposable inboxes create accounts instantly.
- Weak password policy / no leaked-password check → credential stuffing succeeds. See Lovable password protection.
- Site URL / redirect allowlist left as
localhostor*→ OAuth token theft / open redirects. - Session only enforced in React routes, not RLS → curl still dumps tables.
Backend Infrastructure & Deployment
Supabase manages the PostgreSQL database, including backups, connection pooling (via PgBouncer), and automatic scaling on paid plans. Edge Functions run on Deno Deploy, providing serverless compute for tasks like payment processing, email sending, or third-party API calls that need server-side secrets.
Static assets (the compiled React app) are served from a CDN with aggressive caching. API requests go directly from the browser to the Supabase project endpoint. There is no middleware layer or API gateway between the frontend and Supabase – this is both a simplicity advantage and a security consideration.
For production deployments, Lovable supports custom domains with automatic SSL provisioning, environment variable management, and GitHub integration for version control. Database migrations are managed through Supabase’s migration system.
Edge Functions: the privileged surface
Edge Functions are where you keep OpenAI keys, Stripe secrets, and elevated DB operations. Common failures:
- Deployed with
--no-verify-jwtfor convenience. - Uses
service_rolefor every query, then filters “in application code” that never runs for direct REST callers. - Returns stack traces or env dumps on error.
- No rate limit → one user drains your LLM budget.
// Prefer: verify user JWT, use user-scoped client when possible
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
Deno.serve(async (req) => {
const auth = req.headers.get("Authorization");
if (!auth) return new Response("Unauthorized", { status: 401 });
const supabase = createClient(
Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_ANON_KEY")!,
{ global: { headers: { Authorization: auth } } },
);
const { data: { user } } = await supabase.auth.getUser();
if (!user) return new Response("Unauthorized", { status: 401 });
// business logic with RLS still in force
return Response.json({ ok: true, user: user.id });
});
Reserve service_role for admin jobs that cannot express the rule in RLS — and never accept raw IDs without an ownership check when you do.
SOC 2 & GDPR Compliance Status
Supabase holds SOC 2 Type II certification and is GDPR compliant. This covers the database infrastructure, authentication service, storage, and edge functions. Supabase offers data residency options, allowing projects to be hosted in specific AWS regions (US, EU, Singapore, etc.).
Lovable as a platform has not independently published SOC 2 certification as of early 2026. The AI code generation service, project hosting, and deployment pipeline are separate from Supabase’s certified infrastructure. For regulated industries, this distinction matters.
Ultimately, app-level compliance is the developer’s responsibility. Even with SOC 2-certified infrastructure, a Lovable app without RLS policies, without proper data handling, or with exposed secrets fails compliance requirements. The platform provides the building blocks, but developers must configure them correctly.
Security Risks in Lovable’s Architecture
The biggest security risk is the gap between platform security and application security. Supabase’s infrastructure is well-secured, but AI-generated code frequently ships with misconfigured security settings. Common issues include:
- Missing RLS policies – Tables created without RLS enabled are publicly readable and writable through the anon_key. This is the most common vulnerability in Lovable apps.
- Exposed anon_key abuse – While the anon_key is designed to be public, it still grants access to any table without RLS. Attackers extract it from the frontend bundle and query the database directly.
- No server-side validation – Lovable apps often validate data only in the React frontend. Without Edge Functions or database constraints, malicious users can submit arbitrary data by calling the Supabase API directly.
- Overly permissive RLS – AI sometimes generates RLS policies that look correct but use flawed logic, such as checking the wrong column or allowing broader access than intended (
USING (true)). - Public Storage buckets for “avatars” that also hold ID documents.
- Realtime channels without filters broadcasting all row changes.
- Orphan tables from iterative prompts left without policies.
These are not platform vulnerabilities – they are application-level misconfigurations that AI code generation introduces. Securing a Lovable app requires manual review of every RLS policy, every Edge Function, and every client-side data flow.
Recon path an attacker uses
- View source → find
supabase.coURL + anon JWT. GET /rest/v1/with the anon key → OpenAPI of all public tables.GET /rest/v1/<table>?select=*→ dump if RLS is off.- Storage list/public object URLs for files.
- Try RPC endpoints under
/rest/v1/rpc/.
The Supabase RLS Checker automates steps 1–3 against your live deploy.
Frontend-specific risks (Vite + React)
import.meta.env.VITE_*is always public. Never put service_role or Stripe secret underVITE_.dangerouslySetInnerHTMLon user or LLM content → XSS. Prefer text nodes or a sanitizer.- Client-only route guards (
if (!user) navigate('/login')) do not protect data — RLS does. - Source maps in production aid reverse engineering of any remaining secrets.
# Fail the build if a service role-shaped JWT or secret key is in the dist
grep -rE 'service_role|sk_live_|sk-[A-Za-z0-9]{20,}' dist/ && exit 1 || true
Database constraints the generator skips
RLS is necessary; it is not a substitute for integrity:
alter table orders
add constraint orders_amount_positive check (amount > 0);
alter table profiles
alter column email set not null;
-- Prevent clients from self-promoting
-- (pair with policy that forbids changing role unless service_role)
Add CHECK / NOT NULL / FK constraints for money, roles, and tenancy columns.
Production Deployment Best Practices
Before launching a Lovable app to production, complete this checklist:
- Enable RLS on every table and verify policies with test queries (two users, cross-read fails).
- Confirm the service_role key is not present in any frontend code or VITE_ env.
- Set up a custom domain with HTTPS; lock OAuth redirect URLs to that domain.
- Move sensitive logic (payments, emails, API calls) to Edge Functions with JWT verification.
- Add database constraints (NOT NULL, CHECK, UNIQUE) beyond what Lovable generates.
- Enable Supabase Auth email confirmation + leaked password protection.
- Enable rate limiting / bot protection on Auth endpoints where available.
- Review Supabase Dashboard logs for unexpected access patterns after launch.
- Test authorization by attempting to access other users’ data with the anon key and with a second account JWT.
- Set security headers if your host allows them; verify with the Security Headers Checker.
- Audit Storage buckets and Realtime filters.
- Run VibeEval on the production URL.
- Document your Supabase project ref, regions, and who has dashboard Owner access.
- Confirm backups/PITR meet your recovery goals on the Supabase plan you pay for.
- Re-run the checklist after any prompt that adds tables, buckets, or functions.
Lovable gets you to a working prototype fast. The gap between prototype and production-ready is security configuration – and that gap is entirely the developer’s responsibility to close.
Launch-day vs week-two risk
Launch day failures are usually missing RLS and leaked keys. Week-two failures are regression: a new table without policies, a Storage bucket flipped public for a marketing asset that shares the bucket with ID scans, an Edge Function copied from a tutorial with JWT verification off. Calendar a recurring scan; do not treat security as a one-time gate.
Request path: browser to Postgres
Understanding the wire path explains why missing RLS is fatal:
React component
→ supabase.from('invoices').select('*')
→ HTTPS to https://<ref>.supabase.co/rest/v1/invoices
→ Headers: apikey: <anon>, Authorization: Bearer <user JWT or anon>
→ PostgREST applies GRANT + RLS as the DB role for that JWT
→ Rows returned to the browser (or error)
There is no Lovable-owned API gateway rewriting that query. Your policies are the API authorization layer. Client-side filters like .eq('user_id', user.id) are UX convenience — they are not security if RLS is off (attackers omit the filter).
Realtime and Storage follow the same trust model: JWT identity in, policy decision out.
shadcn/ui, Tailwind, and XSS surface
The UI kit is not a major vuln source by itself — React’s default escaping helps — but Lovable apps still grow HTML sinks:
- Markdown preview for invoices/notes without sanitization
dangerouslySetInnerHTMLfor “rich” CMS fields- SVG uploads served as
image/svg+xmlwith embedded script - Reflecting error messages from Supabase into the DOM unsafely
Prefer text content or a vetted sanitizer (DOMPurify) for any user- or LLM-generated HTML. CSP headers are harder on fully managed Lovable hosting; still set them when you control the domain/CDN. See prototype pollution and DOM attacks for related client issues.
Environment variables and build-time secrets
Vite inlines import.meta.env.VITE_* into the client bundle at build time. That means:
| Variable pattern | Visibility | Allowed examples |
|---|---|---|
VITE_SUPABASE_URL |
Public | Project URL |
VITE_SUPABASE_ANON_KEY |
Public | Anon JWT |
VITE_STRIPE_PUBLISHABLE |
Public | pk_live_... |
VITE_SUPABASE_SERVICE_ROLE |
Breach | Never |
VITE_OPENAI_KEY |
Breach | Never |
VITE_STRIPE_SECRET |
Breach | Never |
Server-only secrets belong in Edge Function secrets or a backend you control — never in Vite-prefixed env. After any accidental leak, rotate; scraping bots archive JS bundles.
Data model patterns Lovable generates
Typical first schema for a multi-user app:
profiles(id references auth.users)- feature tables with
user_id - optional
storagepaths under user folders
What usually goes wrong next:
- Join tables for teams without membership checks in RLS.
- Secondary tables (
line_items,comments) with RLS only on the parent. - Denormalized
emailon public-readable rows for “display convenience.” role/is_admin/plancolumns writable under UPDATE policies.
Hardening the data model:
-- Example: line items inherit access from parent invoice
create policy "read line items via invoice ownership"
on line_items for select
using (
exists (
select 1 from invoices i
where i.id = line_items.invoice_id
and i.user_id = auth.uid()
)
);
Every new table in a chat prompt needs the same treatment as invoices — orphan tables are the classic week-two leak.
Realtime, presence, and broadcast
Lovable demos love live dashboards. Security notes:
postgres_changesmust not subscribe to unfiltered sensitive tables.- Presence channels can leak who is online if channel names are guessable and auth is loose.
- Broadcast messages are not a substitute for server authorization when they trigger privileged side effects.
Prefer channel names that include unguessable ids and RLS that would hide the underlying rows anyway. Defense in depth.
Migrating off Lovable hosting without losing controls
Teams export to GitHub and deploy to Vercel/Netlify while keeping Supabase. Security work that must travel with the code:
- Env var mapping: rename carefully — do not promote service role to
NEXT_PUBLIC_/VITE_. - Redirect URLs and Site URL in Supabase Auth for the new domain.
- CORS and headers on the new host.
- CI scan gate on preview URLs (CI/CD guide).
- Re-run RLS and token leak checks after the first export build — bundlers rearrange what appears in assets.
The stack stays “Lovable-shaped” long after the subdomain changes; fingerprinting tools still light up Supabase + Vite + shadcn.
Operational monitoring for this stack
- Supabase Auth logs: spike in signups / token errors
- API logs: bulk
selecton large tables - Edge Function logs: 5xx with stack traces (fix: generic client errors)
- Stripe: webhook failures and signature errors
- Uptime on the SPA is not a security signal — open RLS still returns 200
How this stack compares
| Concern | Lovable stack | Typical Bolt/v0 + custom backend |
|---|---|---|
| Default backend | Supabase only | Whatever you wire |
| Failure modes | Predictable: RLS, keys, BOLA | Variable by backend |
| Auth | Supabase Auth | NextAuth / Clerk / custom |
| Speed to demo | Very high | High |
| Speed to secure prod | Depends on RLS discipline | Depends on middleware discipline |
See Is Lovable Safe? for the three-gap model and Lovable security guide for the operational checklist. For builder comparisons, Bolt vs Lovable security maps failure profiles side by side.
Stack diagram in words
Browser React SPA → Supabase Auth + PostgREST + Storage + optional Edge Functions → Postgres. Hosting may be Lovable’s host or exported to Vercel. Each arrow is a trust boundary.
Where to put business logic
Prefer Postgres constraints + RLS + Edge Functions with user JWT over “smart clients.” Clients are hostile. Generators bias logic into the client for speed — push it back server-side before launch.
Observability stack
Enable Supabase logs, ship to a provider, alert on bulk REST exports and spikes of 401/403. Without observability, RLS bugs become silent breaches.
React Router auth gates are not API auth
Lovable SPAs commonly wrap routes:
function Private({ children }: { children: React.ReactNode }) {
const { session } = useAuth();
if (!session) return <Navigate to="/login" />;
return children;
}
That only affects navigation. The network tab still shows apikey + JWT; attackers skip the router entirely. Teach every new engineer on this stack: private route ≠ private data. RLS and Edge Function JWT checks are the real gates.
shadcn form patterns and mass assignment
Generated forms often bind every column on a profiles type, including role and plan. Prefer explicit Zod schemas that omit privileged fields, and Postgres policies / triggers that reject changes to those columns from authenticated.
Stripe + Lovable stack
Correct pattern: Checkout Session created in an Edge Function; webhook verifies signature; DB update uses service role inside the function after signature check; client never sends paid: true. Wrong pattern: client updates subscriptions row after Stripe.js success event only. See Stripe webhook pattern.
Detecting this stack in the wild
Use the Lovable detector for inventory. Fingerprints: Vite chunks, shadcn/Radix, supabase.co REST, sometimes data-lov-id. Attackers use the same signals (vibe hacking); defenders should inventory first.
Postgres grants that surprise teams
Even with RLS on, PostgREST needs GRANT to anon/authenticated. Over-broad grants plus weak policies equal exposure. Under-grants break the app and tempt USING (true). Review:
select grantee, table_name, privilege_type
from information_schema.role_table_grants
where table_schema = 'public';
Pair grant review with policy review in every schema migration.
TypeScript types are not authorization
Generated Database types from Supabase make client calls type-safe — they do not prevent calling .from('invoices').select('*') without filters. Types reduce typos; RLS reduces breaches. Do not let a green TypeScript build substitute for dual-user HTTP tests.
Related Resources
Is Lovable Safe?
Safety analysis of Lovable for production use
Lovable Security Checklist
Step-by-step checklist for securing Lovable apps
Supabase RLS Checker
Prove every table blocks the anon key correctly
Token Leak Checker
Catch service_role and LLM keys in the Vite bundle
Bolt vs Base44 Tech Stack
Compare adjacent AI full-stack generators
Glossary for this stack
| Term | Meaning here |
|---|---|
| Anon key | Public JWT in the browser; power limited by RLS |
| Service role | Server JWT that bypasses RLS |
| PostgREST | HTTP API over Postgres used by supabase-js |
| RLS | Row Level Security policies in Postgres |
| Edge Function | Deno serverless function on Supabase |
| Vite env | VITE_* inlined into client bundles |
Keep this glossary in onboarding docs so new builders stop treating the anon key as a password.
When to add a real backend in front of Supabase
Stay on the pure Lovable stack while:
- Tenancy is simple (user owns rows)
- Write rates are modest
- Business rules fit SQL policies and a few Edge Functions
Introduce a dedicated API (or migrate to Next.js route handlers with a locked-down Supabase service role) when:
- Complex workflows need transactions across many tables with rules hard to express in RLS
- You must hide schema details from the client entirely
- Compliance requires a server audit log of every mutation with application context
- You are multi-region with custom caching that must not serve cross-tenant data
Moving to a custom API without fixing ownership checks only relocates BOLA. Architecture change is not a substitute for authorization design.
Audit Your Lovable App’s Security
VibeEval automatically scans your Lovable app for missing RLS policies, exposed keys, and authentication flaws. Get a full security report in minutes — stack-aware probes against the same React + Supabase surface this architecture describes.
AUDIT THE FULL LOVABLE STACK
RLS, anon-key abuse, open Storage, and BOLA on generated CRUD — the stack-specific checks that matter after you ship.
14-day free trial · No credit card · Cancel anytime