← All guides

What breaks in Lovable apps: data from 190 live apps

By Novruz Veliev, Senior QA Engineer · ShipClarity

I ran the same outside-in scan against 190 live apps listed as built with Lovable. No login, no account, nothing a normal visitor's browser could not see. 189 of them had at least one flagged issue. Here is what came up most, what almost never came up, and how to check each item on your own app in about two minutes.

This is aggregate data only. No app names and no domains are published here, and none will be. The scan ran on 11 September 2026.

The numbers
In this article
  1. How the data was collected, and what it cannot see
  2. 189 of 190 had at least one flagged issue
  3. 94% send no Content-Security-Policy
  4. 91% send no X-Frame-Options
  5. 79% return 200 for a missing page
  6. 67% have no enforcing DMARC
  7. 3 apps ship an API key in the bundle
  8. What held up

How the data was collected, and what it cannot see

The starting point was a public directory of projects built with Lovable: 512 listings. 428 of them were still live, and 395 of those were in English. After removing portfolios, games, agency pages and pages with no product surface (no pricing, payments, or signup), 190 apps were left, and all 190 scanned without errors. 155 run on their own domain; 35 are on a platform subdomain such as *.lovable.app. Some have since moved hosting to Vercel or Netlify, so read this as "apps built with Lovable", not "apps hosted by Lovable".

Each app got the same 17 automatic checks that the free ShipClarity scanner runs: exposed config and repo files, secret keys in the JavaScript bundle, whether a Supabase project answers schema requests with only the public key, source maps, SPF, DKIM and DMARC, HTTPS and the HTTP redirect, four security headers, the mobile viewport tag, robots.txt and noindex, the status code of a missing page, and first-response time.

What this data cannot tell you

1189 of 190 had at least one flagged issue

Only one app out of 190 came back clean. The average was 4.1 flagged checks out of 17, the median 4, the worst 8. Most of that count comes from the four items below, which are configuration defaults nobody revisited, not code bugs. That matters for how you read the number: "99% have issues" does not mean 99% are broken for users. It means almost nobody went back over the defaults after the app started working.

Check yours in 2 minutes

Run the free scan on your URL. It is the same 17 checks used for this dataset, takes about 20 seconds, and needs no signup.

294% send no Content-Security-Policy

179 of 190 apps send no Content-Security-Policy header. CSP is the browser-side rule that says which scripts are allowed to run on your page. Without it, any script that gets injected (through a compromised third-party widget, or user content rendered without escaping) runs with full access to the page, including whatever the logged-in user can see.

This is a hosting or proxy setting, not something the AI builder writes into your app code, which is why it is missing almost everywhere.

Check yours in 2 minutes

curl -sI https://yourapp.com | grep -i content-security-policy

No output means no header. Without a terminal: open DevTools, Network tab, reload, click the first request (the document), and look under Response Headers. If your host does not let you set response headers, a proxy in front of the domain (Cloudflare, or Netlify/Vercel header rules) can add them. Start with Content-Security-Policy-Report-Only so a strict policy does not break your own scripts on day one.

391% send no X-Frame-Options

172 of 190 apps send no X-Frame-Options header. 171 of them send no CSP either, so there is no frame-ancestors rule covering the gap. That means another site can load the app inside an invisible iframe and trick a logged-in user into clicking something real: a delete button, a plan change, a share toggle.

Two more headers from the same family, for completeness: 44 of 190 (23%) lack X-Content-Type-Options: nosniff, and 23 of 190 (12%) lack HSTS.

Check yours in 2 minutes

curl -sI https://yourapp.com | grep -i -E "x-frame-options|frame-ancestors"

You want either X-Frame-Options: DENY (or SAMEORIGIN) or a CSP containing frame-ancestors 'none'. Note that frame-ancestors is ignored inside a <meta> CSP tag; it only works as a real response header.

479% return 200 for a missing page

150 of 190 apps answered 200 OK when asked for a random URL that does not exist. This is the single-page-app default: the host serves index.html for every path and lets the front-end router decide what to show. The visitor may see a "not found" screen, but search engines and uptime monitors see a healthy page.

Two practical costs. Search engines can index junk or mistyped URLs and flag them as soft 404s. And a monitor that pings a route will keep reporting "up" after that route has been deleted or renamed.

Check yours in 2 minutes

curl -s -o /dev/null -w "%{http_code}\n" https://yourapp.com/this-page-does-not-exist

If it prints 200, open the same URL in a browser too. A blank page or the home page is worse than a "not found" screen. The minimum fix is a catch-all route that shows a clear not-found page and adds <meta name="robots" content="noindex">. A real 404 status needs a host-level rule.

567% have no enforcing DMARC

127 of 190 apps have either no DMARC record at all (50) or one set to p=none (77), which only monitors and blocks nothing. All 127 are on their own domain: counted against the 155 custom domains in the set, that is 82%. The 35 apps on a platform subdomain inherit the platform's record. On top of that, 52 custom domains (27% of all apps) have no SPF record either.

Without an enforcing DMARC policy, anyone can send email that claims to be from your domain, and your own signup and password-reset emails are more likely to land in spam. If that second part sounds familiar, there is a separate guide: Lovable password reset email not arriving.

Check yours in 2 minutes

dig TXT _dmarc.yourdomain.com +short          # macOS / Linux
nslookup -type=TXT _dmarc.yourdomain.com      # Windows

No answer means no record. p=none means monitor-only. The target is p=quarantine or p=reject, but only after SPF and DKIM are set up for the provider that actually sends your mail. Switching to reject before that will block your own emails.

63 apps ship an API key in the bundle

3 of 190 apps had a key matching a known secret pattern in the JavaScript sent to every visitor. All three were Google/Firebase API keys (the AIza... format). That is less dramatic than it sounds: this type of key is designed to sit in client code, and it is fine as long as it is restricted by HTTP referrer and by API in the Google Cloud console. An unrestricted one can be copied and used on someone else's site at your expense.

The more useful number is the zero: none of the 190 shipped a Supabase service_role key, a Stripe live secret key (sk_live_), or an AWS access key in the scanned bundles. Those are the ones that would hand over the database or the payment account. The Supabase anon key, which most of these apps do ship, is public by design and was not counted as a finding.

Check yours in 2 minutes

Open your live app, open DevTools, press Ctrl+Shift+F (Cmd+Option+F on a Mac) to search across all loaded files, and search for service_role, sk_live_, AKIA and AIza. A hit on the first three means rotate the key now and move the call to a server-side function. A hit on AIza means open Google Cloud Console, Credentials, and confirm the key has both a referrer restriction and an API restriction.

7What held up

The scary items were rare. Out of 190 apps:

A closed schema endpoint is a good sign, not a clean bill of health. Whether user A can read user B's rows depends on the row-level security policy of each table, and that can only be tested with two real accounts.

Check yours in 2 minutes

curl -s -o /dev/null -w "%{http_code}\n" https://yourapp.com/.env
curl -s -o /dev/null -w "%{http_code}\n" http://yourapp.com/

The first should not be 200 with real file contents (a 200 that returns your normal app page is the soft-404 behaviour from point 4, not a leak). The second should be a 301 or 308 redirect to HTTPS.

What to take from this

Everything above is visible from outside, and almost all of it is configuration: headers, DNS records, a catch-all route. An afternoon covers it. None of it tells you whether the app works for a paying user. The failures that cost customers live behind the login, where no scanner goes: a signup that silently fails, a reset link that points at the old preview domain, one account seeing another account's data, a checkout that charges twice. This dataset says nothing about how common those are, because it could not look.

See where your own app stands

The free scanner runs the same 17 checks used for this dataset on your URL. About 20 seconds, no login, no signup.

Run the free scan Send me your URL

Prefer a person to look? Leave your URL in the form on the home page and I will reply within 24 hours with 3 things I found by hand. Free, no call.