Secrets are the easiest way to break a “working” AI-generated app
React + Supabase is a fast, friendly stack—and it’s also a stack where secret handling is easy to get subtly wrong. AI-generated code makes this more likely: the app compiles, auth works, and then a key lands in a client bundle, a Git commit, a screenshot, or an error log. The result isn’t theoretical: leaked keys lead to database abuse, unexpected bills, and incident response work you didn’t plan for.
This playbook focuses on practical leakage prevention and safe rotation for AI-generated React + Supabase apps, including projects created with lovable.dev, where you can iterate quickly while still keeping secrets out of the frontend and out of Git.
Know what is and isn’t a secret in Supabase
Public keys you can ship
Supabase apps typically use a project URL and an anon key in the browser. That anon key is designed to be public. Treat it like a username, not a password: it’s only safe if your Row Level Security (RLS) policies are correct. If RLS is missing or permissive, a public anon key becomes a data-exfil path.
Keys that must never reach the browser
- Service role key (bypasses RLS): keep server-side only.
- Database password / direct Postgres credentials: never embed in apps, never log.
- Third-party secrets (Stripe secret key, webhook signing secret, OAuth client secret): server-only.
If an AI tool generates a “quick fix” that puts the service role key into a React env var, treat it as an incident, not a refactor task.
The two rules that prevent most secret leaks
Rule 1: Anything in a React build is public
Client environment variables are not secret. Even if hidden behind a build step, anything bundled into the frontend can be read by users, proxies, browser devtools, or crawlers. Many leaks happen because developers confuse “env var” with “secret.” In the browser, an env var is just a convenient string substitution.
Rule 2: Data access must be constrained by policy, not key privacy
Assume your anon key is public and design around it. The real protection is:
- RLS enabled on every table that can be reached from the client
- Policies scoped to
auth.uid()and explicit roles - Least-privilege columns and views (avoid
select *patterns for sensitive tables)
Common AI-generated mistakes and how to catch them fast
Mistake: Service role key in the frontend
Symptom: code initializes Supabase with a service role key or uses server-only admin operations from React. Fix: move that logic to a server endpoint (serverless function, edge function, or backend) and only call it from the client.
Mistake: “Temporary debugging” that prints secrets
AI-generated troubleshooting often adds console.log(process.env…) or dumps config objects. These logs end up in hosted logs, error reporting, screen recordings, and shared tickets. Fix: remove logs, rotate exposed keys, and add a lint rule or pre-commit check to block process.env logging.
Mistake: Copy/paste from a dashboard screenshot
When building quickly, it’s easy to paste a key that was visible in a screenshot or a doc. Fix: treat any key that appeared in a shared artifact as compromised and rotate it.
A practical environment variable layout for React + Supabase
Client (React) variables
Keep only what you are comfortable publishing:
VITE_SUPABASE_URL(or framework equivalent)VITE_SUPABASE_ANON_KEY
In code review, if you see anything like SERVICE_ROLE, POSTGRES, STRIPE_SECRET, or WEBHOOK_SECRET in frontend env vars, stop and redesign.
Server variables
These live in your server runtime (functions/edge/backend), not in the React build:
SUPABASE_SERVICE_ROLE_KEYDATABASE_URL(if used)STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET
Server code is where you should perform privileged writes, admin reads, and third-party API calls that require secrets.
Rotation playbook that doesn’t break production
1) Decide what triggered rotation
Rotation isn’t only for “confirmed leaks.” Rotate when:
- a secret was committed to Git, even briefly
- a secret appeared in logs, screenshots, support tickets, or issue trackers
- a contractor or former teammate had access you can’t fully audit
- you changed a hosting provider or CI system permissions
2) Inventory dependencies before changing anything
List every place the secret is used: production functions, preview deployments, local dev, CI, cron jobs, webhook endpoints. AI-generated apps often have “hidden” usage (a quick script, a one-off function, or an integration step) that will fail silently after rotation.
3) Perform a two-phase cutover when possible
For secrets that support multiple active versions (for example, webhook signing secrets or API keys in some providers), add the new secret first, deploy code that accepts both, then remove the old secret. Where dual-running isn’t possible, schedule a short maintenance window and prepare a rollback plan.
4) Rotate, redeploy, verify, then revoke
- Rotate the credential at the provider
- Update server env vars
- Redeploy functions/backends
- Run a verification checklist (auth, writes, webhooks, background jobs)
- Revoke the old credential
Verification should include “negative” tests too: confirm the old key truly fails, not just that the new key works.
Leakage prevention that fits fast iteration
Block secrets before they land in Git
Use pre-commit scanning and CI checks to detect common token formats. Even lightweight scanning catches the majority of accidental commits. Also ensure .env files are ignored and avoid sharing them in chat tools.
Normalize tool inputs when using MCP or automations
Secrets leak when toolchains accept untrusted inputs and pass them through to logs, prompts, or API calls. If you’re adding custom connectors via MCP servers, adopt canonical schemas and input normalization to prevent “tool confusion” classes of issues. The same discipline that protects secrets also improves reliability in multi-step automation. For a deeper look at this defensive pattern, see Mitigating MCP Tool Confusion Attacks with Canonical Schemas and Input Normalization.
Keep production keys out of demos and support flows
AI builders encourage sharing context—screenshots, console outputs, export zips. Build a habit: use separate projects for demos, use scoped keys, and strip logs before sharing. If you need verifiable claims without exposing internals, structured “snippet packs” can help teams share evidence safely. Related: Ground-Truth Snippet Packs for Verifiable AI Claims.
RLS and backend boundaries that make public keys safe
A good target architecture is simple:
- Frontend uses anon key and only accesses RLS-protected tables
- Privileged operations run in server functions using service role
- All third-party secret integrations happen server-side
When you generate apps quickly—especially in tools like Lovable that produce React + Supabase projects and can sync to GitHub early—the best security outcome is achieved by establishing these boundaries immediately and keeping the iteration loop inside them.



