AI-coded apps

    What should I check in my Lovable app before App Store submission?

    Lovable.dev workspace security view showing the RLS analysis, database security check, code review, and dependency audit scanners before a publish to App Store Connect

    You are about to submit a Lovable.dev build to the App Store or Google Play, and the open question is whether the app is ready or whether reviewers, or worse, your own users, will find the holes first. Lovable now runs an automated security check before publish, but audits of real production Lovable repos keep surfacing the same handful of issues. This is the pre-submission pass to make before the store does it for you.

    Short answer

    The short answer is to verify five things before you hit publish: Supabase Row Level Security on every sensitive table, no service role key or third-party secret in the browser bundle, server-side validation inside Edge Functions, store privacy disclosures that match what the app actually collects, and basic security headers on the production domain. Lovable's built-in scan covers parts of the first three, per its security overview, but the dev.to audit titled Is Lovable Actually Secure? I Checked the Supabase RLS on 50 Apps, published in 2025, found that roughly 89% of the sampled apps had missing or permissive RLS and 34% shipped the service role key to the browser. Both are the kind of issue that becomes a Guideline 5.1.1 or 1.6 rejection once a reviewer opens DevTools.

    What you should know

    • The automatic pre-publish scan is a floor, not a verdict. Lovable runs RLS analysis, database security check, code review, and a dependency audit when you open the publish dialog, per its security overview. The four scanners are static analysis, not a live probe.
    • App Review reads the data path. Guideline 1.6 covers data security and Guideline 5.1.1 covers data collection. Reviewers do open the network tab and compare what they see against the privacy policy URL.
    • The service role key is the single most expensive mistake. A key bundled in the browser bypasses every RLS policy because the role has BYPASSRLS in the Postgres cluster.
    • Edge Functions are where validation belongs. Client checks improve user experience; they cannot enforce anything on a request crafted with curl.
    • Privacy nutrition labels live in the store listing. A mismatch between what the app collects and what App Store Connect declares is a fast Guideline 5.1.2 rejection.
    • Security headers are a separate scan. Most Lovable production domains score poorly on common header tests out of the box, and that surfaces in third-party scanners reviewers sometimes run.

    What does Lovable's pre-publish security scan actually cover?

    The short answer is four scanners: RLS analysis, database security, code review, and dependency audit. According to Lovable's security feature page, all four run automatically when you open the publish dialog and can be triggered on demand from the Security view inside the workspace.

    The mechanism is static analysis against the project. The RLS analyzer flags overly permissive policies or missing access checks. The code review hunts for hardcoded keys and obvious anti-patterns. The dependency audit reads the lockfile for known vulnerable versions. None of these run a live probe against the deployed PostgREST endpoint or simulate a hostile request with a forged JWT.

    That gap is where most leaks live. A policy of using (true) is loud enough that the scanner flags it, but a subtler mistake (a write policy keyed on auth.role() = 'anon', an UPDATE policy with USING but no WITH CHECK) can pass static analysis and still let users rewrite ownership. Public incident reports back this up: the widely covered early-2026 Lovable leak that exposed personal data on a single Discover-page app surfaced even though the workspace's automated checks did not raise an alert before the researcher disclosed.

    The fix is to treat the scan as the first of two passes. Run it, fix every finding, then walk the manual checklist below before opening App Store Connect or Google Play Console.

    The limit is that the scanner does not currently exercise authorization bypass in Edge Functions or read Supabase Storage bucket policies. Both have to be verified by hand.

    Why is Supabase Row Level Security the first thing to verify?

    The short answer is that any Lovable table with grants but no enforced policy is reachable from the public PostgREST endpoint, and the data path is the first thing a reviewer or attacker will probe.

    The mechanism is documented in Supabase's row level security guide: PostgREST receives a JWT, maps it to the anon, authenticated, or service_role Postgres role, and runs policies on every operation. When RLS is disabled and grants exist on the public schema, every row is reachable with the publishable anon key, no authentication required.

    The evidence is the same dev.to audit: roughly 89% of the sampled apps had missing or permissive RLS, 34% shipped the service role key in the browser bundle, and 28% queried auth.users directly instead of creating a profiles table. Those are observed patterns from a community sample, not Apple or Google statistics, but they map cleanly onto the kind of evidence reviewers cite in Guideline 1.6 rejections.

    The fix has three steps. First, run alter table ... enable row level security on every table in the public schema. Second, write a SELECT, INSERT, UPDATE, and DELETE policy per table, each predicate keyed on auth.uid() rather than a client-supplied column. Third, verify from an incognito browser with the anon key, not from the Supabase Table Editor, which runs as service_role and bypasses RLS by design.

    The limit is that Supabase Storage uses a separate policy surface in the storage schema. A perfectly locked public.profiles table can still leak avatars if the avatars bucket is public or its policy reads using (true).

    Which Lovable keys and secrets must stay out of the browser bundle?

    The short answer is every server-only credential. The publishable anon key is meant to be public and can ship in the bundle; the service role key, third-party API keys (Stripe, SendGrid, OpenAI, Resend), database connection strings, and webhook signing secrets cannot.

    The mechanism follows from how Vite ships environment variables. Anything prefixed with VITE_ is inlined into the production bundle at build time and is readable in DevTools. Lovable's guidance is direct: per the avoiding security pitfalls page, "secrets stored in frontend code are visible to users and should be considered compromised."

    The evidence is in the same community audit: 22% of the sampled apps placed sensitive values behind VITE_ or NEXT_PUBLIC_ prefixes. The dependency audit will not catch this on its own because the values live in environment files, not in node_modules.

    The fix is to move every third-party API call into a Supabase Edge Function and store the secret in the Lovable Secrets panel or in Supabase project secrets. The Edge Function reads the secret from its server environment, makes the outbound call, and returns only the result to the client. The publishable anon key is the only Supabase credential that belongs in the browser.

    What belongs in an Edge Function instead of the app?

    The short answer is authorization, validation, and any external call that uses a secret.

    The mechanism is the standard server boundary. Per the Lovable security pitfalls page, "frontend validation improves user experience but provides no security guarantees." A user can replay any request with a modified payload using curl or a browser console, and the only enforceable defence is on the server.

    A practical Edge Function takes the user JWT from the Authorization header, calls supabase.auth.getUser() to verify it, runs explicit checks (does this user own the record, is the input within bounds, does the rate limit allow another call), then performs the privileged action through the user-scoped client. RLS still runs underneath, which is why the JWT-forwarding pattern, rather than the service role pattern, is the right default for most Lovable Edge Functions.

    The evidence is the same audit: 18% of Lovable apps had zero input validation on writes, and the typical Lovable form posts directly to a Supabase table via the JS client. That is acceptable when RLS is correct and column types prevent type confusion, but it leaves no room to enforce business rules.

    How do App Store and Google Play rules map onto a Lovable submission?

    Most Lovable apps that reach the stores ship through a wrapper, usually Capacitor, a progressive web app shell, or a third-party packager that produces an IPA or AAB from the Lovable build. The store rules apply to that compiled bundle, not to the dev preview URL.

    Lovable concernApp Store ruleGoogle Play rule
    Missing privacy policy URLGuideline 5.1.1(i): privacy policy required in App Store Connect and in-appData Safety form plus a public privacy policy URL
    Service role key in bundleGuideline 1.6: appropriate data securityPlay Console User Data policy, deceptive behavior
    RLS off, public read of users tableGuideline 5.1.2(i): unauthorized accessPlay Console User Data policy
    Privacy nutrition label mismatchGuideline 5.1.2(i): undeclared data useData Safety inaccuracies, common rejection ground
    Third-party SDK without disclosureGuideline 5.1.1(iii) plus Privacy Manifest required reasonsSDK disclosures in Data Safety
    Hardcoded third-party AI calls in clientGuideline 5.1.2(i): third-party AI sharing must be disclosedGenerative AI policy plus Data Safety

    According to the Apple App Review Guidelines, Section 1.6 requires "appropriate security measures to ensure proper handling of user information," and Section 5.1.1 requires that the privacy policy clearly identify what is collected and how. For Capacitor wrappers, you also need a PrivacyInfo.xcprivacy file with required-reason declarations for any framework API the wrapper imports.

    For builders who want an outside read of the same checklist on the compiled wrapper before it uploads, PTKD.com (https://ptkd.com) is one of the platforms focused on pre-submission static analysis aligned with OWASP MASVS for AI-coded and no-code apps, which lines up with the evidence App Review reviewers tend to look for.

    The limit is that store reviewers cannot probe your Supabase backend at depth. Store approval does not prove the data layer is sound; the bigger risk on the database side is your own users.

    What to watch out for

    Three traps appear in Lovable submissions more often than the rest.

    The first is verifying RLS from the Supabase dashboard. Every query in the SQL editor runs as the postgres superuser, and the Table Editor runs as service_role. Both bypass RLS. A leak that is invisible in the dashboard can still be reachable from the browser with the publishable anon key. Reproduce the request from an incognito window, with the same client the app uses.

    The second is treating the Lovable code review scanner as a full audit. It is a static check, helpful but partial. It does not exercise the live API, does not run authorization tests, and does not read Supabase Storage bucket policies. A clean Lovable Security view is consistent with a real leak in the deployed app.

    The third is filling out the App Store privacy nutrition label or the Google Play Data Safety form before listing every SDK and Edge Function the wrapped app calls. A wrapper that pulls in Firebase Analytics, AdMob, or a third-party AI API picks up disclosure obligations that the Lovable preview never surfaces. Guideline 5.1.2 rejections are usually driven by what reviewers see in network traffic compared with what the store listing claims.

    Key takeaways

    • Run the Lovable security scan first, then walk the manual checklist on the same project. The scan is a floor, not a sign-off, and the gaps it does not cover (storage buckets, Edge Function auth, store disclosures) are where rejections come from.
    • Verify Row Level Security from an incognito browser with the publishable anon key, never from the SQL editor or the Table Editor.
    • Move every secret and every privileged call into Edge Functions or server-side Secrets. The publishable anon key is the only Supabase credential that belongs in the browser bundle.
    • Cross-check the App Store privacy label and Google Play Data Safety form against the actual network traffic of the compiled wrapper, not the Lovable preview.
    • For builders who want a calm outside review of a Lovable wrapper before submission, PTKD.com (https://ptkd.com) is one of the scanning platforms focused on AI-coded apps aligned with OWASP MASVS, which gives a second read on the evidence App Review and Play Console care about.
    • #lovable
    • #supabase
    • #rls
    • #app store
    • #google play
    • #edge functions
    • #ai-coded apps
    • #pre-submission

    Frequently asked questions

    Does Lovable's automatic pre-publish scan replace a real security audit?
    No. The four scanners (RLS analysis, database security check, code review, dependency audit) run static checks, per Lovable's security overview. They do not exercise the live PostgREST endpoint, do not test authorization with a real JWT, and do not inspect Supabase Storage bucket policies. A clean Security view inside the Lovable workspace is fully consistent with a real leak in the deployed app, so treat the scan as one input, not a sign-off.
    How do I get a Lovable web app onto the App Store?
    Most builders wrap the Lovable build in Capacitor, a progressive web app shell, or a third-party packager that produces an IPA for App Store Connect. The App Review Guidelines apply to that bundle. You also need a Privacy Manifest with required-reason declarations for any framework API the wrapper imports, and the App Store Connect privacy nutrition label has to match the data the wrapped app actually collects.
    What is the most common rejection reason for Lovable-built apps?
    Section 5.1.1 (privacy policy and data collection) and Section 1.6 (data security) are the two App Review categories most often cited on AI-coded submissions. Reviewers open the network tab on a Capacitor wrapper and read what the app actually sends. When the privacy policy or the nutrition label does not match the traffic, or when a third-party AI call is undisclosed, the rejection is concrete and fast.
    Does the publishable Supabase anon key need to be hidden?
    No. The publishable anon key is meant to be public and is safe inside the browser bundle, per Supabase's API security documentation. The security boundary is Row Level Security plus the grants, not the key itself. The danger is the service role key, which carries BYPASSRLS and skips every policy; it must stay on the server, either inside Edge Functions or in your Supabase project secrets.
    How do I prove RLS works without trusting the Supabase dashboard?
    Open an incognito window, point the Supabase JS client at your project URL with the publishable anon key, and run select queries against each sensitive table while signed out and signed in. The Table Editor and SQL editor both bypass RLS because they run as service_role and postgres respectively. The browser, with the same key the deployed app uses, is the authoritative oracle for what the public sees.

    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