AI-coded apps

    Lovable.dev exposed your Supabase service_role key. What now?

    Lovable.dev Supabase service_role key incident response

    The reader I am writing for has just opened devtools on their Lovable.dev app, searched for service_role in the bundle, and found a hit. The next ninety minutes decide how much damage that hit translates into. This page is the ordered checklist for those ninety minutes.

    Short answer

    Rotate the service_role key in the Supabase dashboard before reading the rest of this page; it takes ten seconds. Then update any Edge Functions and backend jobs that used the old value, audit your Row Level Security policies, pull at least 60 days of Supabase audit logs, and decide whether to notify users. According to Lovable's official incident response post for the April 2026 disclosure, public project chat histories were readable by any Lovable account between February 3 and April 20, 2026, so any key that touched a chat in that window is also compromised.

    What you should know

    • The service_role key carries the Postgres BYPASSRLS attribute. Every Row Level Security policy is skipped when this role queries the database.
    • Rotation is the only step that closes the window. Editing policies while the key still works leaves the database open to whichever attacker has already grabbed it.
    • Lovable's April 2026 disclosure extends the affected population. Any project that held the key in chat or source between February 3 and April 20, 2026 is in scope, not only projects that exposed the key in the client bundle.
    • User sessions survive the rotation. Existing Supabase Auth JWTs continue to validate; you do not have to log everyone out as part of the fix.
    • The 72-hour GDPR clock starts when you determine personal data was likely accessed. Do not let the rotation work delay the legal notification.

    What does "service_role key in client code" actually mean?

    Lovable.dev compiles its frontend with Vite, which inlines any environment variable starting with VITE_ directly into the JavaScript bundle that ships to every visitor. According to the Vite documentation on environment variables, this is the documented behaviour. Variables without the VITE_ prefix stay server-side and only reach Edge Functions.

    The failure mode is mechanical. A developer adds a VITE_SUPABASE_SERVICE_ROLE_KEY because the AI agent suggested it for a quick admin write, or because they did not know the difference between the publishable key and the secret key. Vite obeys, the build succeeds, and the JWT lands in assets/index-<hash>.js as a string literal. Anyone who opens the Sources tab in devtools can read it.

    The official Supabase documentation on API keys is direct about this scenario: "Never use in a browser, even on localhost," and: "Do not bundle in executables or packages for mobile, desktop or CLI apps." The key was never designed for client code.

    What attacks does it actually enable?

    The service_role key lets the holder run any query the Postgres role can run, which is effectively all of them. In the documented Lovable incidents the observed attacks fall into four categories:

    • Mass read. Select every row from every table. Emails, addresses, payment data, API keys stored as configuration, internal IDs. The Superblocks technical writeup of CVE-2025-48757 lists exactly this pattern across 170 affected apps.
    • Targeted writes. Update payment status, grant admin flags, change pricing tiers. Apps shown in the February 2026 VibeEval audit included an EdTech app where students could grant themselves passing grades by hitting the Supabase endpoint with the leaked key.
    • Deletion. Drop tables, delete user accounts, wipe historical records. Extortion-ware variants in this category have been reported on Supabase community forums since mid-2025.
    • Lateral movement. Use credentials read from one table (Stripe secrets, SendGrid keys, OpenAI tokens) to attack third-party services connected to the same project.

    No authentication is required for any of these. The attacker needs the project URL and the key, both of which are readable in the deployed bundle.

    What is the right rotation sequence right now?

    Order matters because partial fixes leave windows open.

    StepActionTimeWhy this order
    1Rotate the service_role key in Supabase dashboard → Project Settings → API Keys → "Reset service_role key"10 secondsCloses the open window immediately. Every subsequent step assumes the leaked key is dead.
    2Update Edge Functions and backend jobs to the new key value5 to 30 minutesThey were using the old value and will throw 401 until the secret is updated.
    3Audit Row Level Security policies for USING (true) rules and missing policies30 to 60 minutesPermissive policies are usually next to leaked keys; same root cause.
    4Pull 60 days of Supabase audit logs and search for anomalous read patterns10 to 30 minutesDetermines whether you have a notification obligation.
    5Remove sensitive credentials from Lovable chat history5 minutesAny chat-pasted secret should be treated as already compromised per Lovable's own April 2026 incident statement.
    6Notify affected end users where the audit log shows exposureVariableRequired under GDPR within 72 hours if personal data was accessed.

    The first three steps close the technical exposure. The last three close the legal and customer-trust exposure. Both matter; they are separate workstreams that can run in parallel after step 1 is done.

    How do you tell if you have already been exploited?

    Open the Supabase dashboard, go to Logs and Analytics, and filter by the service_role role for the past 60 days. Look for four signal patterns:

    • Query volume that does not match your normal traffic curve. The service_role typically issues hundreds of queries per day from your own backend; thousands in a short burst is suspicious.
    • Source IPs that are not the public IPs of your Edge Function infrastructure or your developer machines. Residential ranges, mobile carriers, or unexpected geographies are the strong signal.
    • SELECT statements with no WHERE clause against user-data tables. Legitimate backend code almost always filters; mass dumps do not.
    • Failed queries against tables that do not exist. Attackers often probe for common table names (users, payments, secrets) before they find your actual schema.

    For mobile apps that bundled a Lovable backend into an APK or IPA, PTKD.com (https://ptkd.com) scans the compiled binary for hardcoded Supabase URLs paired with privileged JWTs, and flags the SDK versions known to have shipped with the issues Supabase has published advisories about. The report maps each finding to the relevant OWASP MASVS control and gives a remediation snippet.

    Why did Lovable users specifically end up in this situation?

    Three contributing factors, in order of how much they matter.

    First, the Lovable AI agent does not consistently distinguish between the publishable (anon) key and the secret (service_role) key when generating code. When asked for an admin write it tends to suggest the simpler-looking pattern, which is to use the service_role key directly from the client. The agent is correct that this works; it is wrong that it is safe.

    Second, the platform's environment variable handling encourages the wrong pattern. As covered in articles 1 and 2 of this journal cluster on AI-coded app safety, the VITE_ prefix causes the variable to be inlined into the public bundle, which is the documented Vite behaviour. The platform does not warn the developer that prefixing a secret key with VITE_ makes it public.

    Third, the April 2026 incident specifically extended the affected population beyond "keys in the bundle." Per Lovable's official statement, public project chat histories and source code were readable by any free Lovable account between February 3 and April 20, 2026. Any developer who pasted the service_role key into a chat while debugging during that 76-day window is in scope, even if the key never appeared in their deployed bundle.

    What to watch out for

    Three details that are routinely missed during the rotation work.

    First, rotation does not invalidate JWTs that were issued by the old key through signInWithCustomToken or similar admin flows. Those are separate tokens that live for their own expiry. If the threat model warrants it, force-rotate user sessions by calling auth.admin.signOut() from a freshly-keyed Edge Function. Most apps do not need this step; data-sensitive apps probably do.

    Second, the AI agent that originally generated the file will sometimes regenerate it. The fix can revert silently on the next prompt that touches the same component. Add a CHANGELOG entry and a comment in the affected file so the next iteration of the AI sees the constraint. Better still, move the entire admin code path into an Edge Function where the agent cannot reach it.

    Third, third-party credentials pasted into Lovable prompts during the February to April 2026 window are also in scope. The Lovable incident statement is specific that chat history was exposed, which means any Stripe secret key, SendGrid token, or OpenAI key shown to the AI during that period should also be rotated. This is a wider scope than most developers realise from a first read of the disclosure.

    Key takeaways

    • The service_role key is the credential to rotate first. Anything else is downstream.
    • Lovable's April 2026 disclosure makes the affected population larger than just "key in the deployed bundle". Pasted-into-chat is also exposed.
    • The full incident response runs about 90 minutes for a small project, longer if you have downstream third-party credentials to rotate.
    • For Lovable apps compiled to mobile, scanning the APK or IPA with PTKD.com (https://ptkd.com) before resubmitting catches the second-order exposure that the web bundle scan can miss.
    • Document the incident, the affected tables, and the user notification decision in your CHANGELOG so the audit trail exists if a regulator asks for it later.
    • #lovable
    • #supabase
    • #service-role-key
    • #rls
    • #incident-response
    • #ai-coded apps

    Frequently asked questions

    How quickly do I need to rotate the key after I notice it was exposed?
    Within minutes. The service_role key bypasses every Row Level Security policy, so the window between discovery and rotation is the window an automated attacker can use to dump or delete data. Rotation in the Supabase dashboard takes seconds; the cleanup work that follows takes hours. Do the rotation first, then deal with everything else.
    Will rotating the service_role key sign my users out?
    No. User sessions are JWTs signed by Supabase Auth and are independent of the service_role key. Existing user sessions keep working through their normal expiry. If the threat model requires force-rotating sessions, call auth.admin.signOut() from a freshly-keyed Edge Function, but this is rarely necessary for the initial rotation step.
    Do I need to tell my users?
    If the project stored personal data covered by GDPR, the 72-hour breach notification clock starts when you determine that personal data was likely accessed by unauthorised parties. For projects without identifiable user data, notification is optional but transparent. The Lovable incident response page suggests the platform will contact affected users directly, but that does not replace your own controller obligations.
    Is changing the Supabase project URL enough?
    No. The service_role key is the credential; the project URL is the address. Rotating only the URL leaves the old key valid against the old project. Always rotate the key. Changing the project URL is sometimes useful as a second step if the old URL is hardcoded into widely-deployed apps that you cannot redeploy.
    What about the April 2026 Lovable chat history breach?
    Lovable disclosed on April 20, 2026 that public project chat history and source code could be read by any Lovable user from February 3 to April 20, 2026. Any credential pasted into a Lovable chat during that window should be treated as compromised, including service_role keys, third-party API keys (Stripe, SendGrid, OpenAI, Anthropic), and any database passwords that appeared in prompts.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free