<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Novruz Veliev</title>
    <description>The latest articles on DEV Community by Novruz Veliev (@novruz_veliev).</description>
    <link>https://dev.to/novruz_veliev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4132221%2Fe7b160c1-7e58-4687-a80b-541cfe0699f4.jpg</url>
      <title>DEV Community: Novruz Veliev</title>
      <link>https://dev.to/novruz_veliev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/novruz_veliev"/>
    <language>en</language>
    <item>
      <title>What breaks in Lovable apps: data from 190 live apps</title>
      <dc:creator>Novruz Veliev</dc:creator>
      <pubDate>Tue, 22 Sep 2026 09:19:18 +0000</pubDate>
      <link>https://dev.to/novruz_veliev/what-breaks-in-lovable-apps-data-from-190-live-apps-5825</link>
      <guid>https://dev.to/novruz_veliev/what-breaks-in-lovable-apps-data-from-190-live-apps-5825</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://shipclarity.app/lovable-apps-what-breaks.html?r=devto" rel="noopener noreferrer"&gt;shipclarity.app&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I ran the same outside-in scan against 190 live apps listed as built with Lovable. No login, 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 a two-minute self-check for each.&lt;/p&gt;

&lt;p&gt;Aggregate data only: no app names or domains are published, and none will be. The scan ran on 11 September 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;189 of 190 (99%)&lt;/strong&gt; had at least one flagged issue (average 4.1, median 4, out of 17 checks)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;179 (94%)&lt;/strong&gt; send no Content-Security-Policy header&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;172 (91%)&lt;/strong&gt; send no X-Frame-Options header&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;150 (79%)&lt;/strong&gt; answer 200 OK for a page that does not exist&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;127 (67%)&lt;/strong&gt; have no DMARC record, or one set to &lt;code&gt;p=none&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3&lt;/strong&gt; ship a Google/Firebase API key in the bundle; none shipped a Supabase &lt;code&gt;service_role&lt;/code&gt; key or a Stripe live secret key&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0&lt;/strong&gt; exposed a &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;.git&lt;/code&gt; or backup file, and &lt;strong&gt;0 of 125&lt;/strong&gt; probed Supabase projects returned their schema to the public key&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How the data was collected, and what it cannot see
&lt;/h2&gt;

&lt;p&gt;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, all scanned without errors. 155 run on their own domain; 35 are on a platform subdomain such as &lt;code&gt;*.lovable.app&lt;/code&gt;. Some have since moved to Vercel or Netlify, so read this as "built with Lovable", not "hosted by Lovable".&lt;/p&gt;

&lt;p&gt;Each app got the same 17 automatic checks that &lt;a href="https://scan.shipclarity.app/?r=devto" rel="noopener noreferrer"&gt;the free ShipClarity scanner&lt;/a&gt; runs: exposed config and repo files, secret keys in the JS bundle, Supabase schema exposure to the public key, source maps, SPF, DKIM and DMARC, HTTPS and the HTTP redirect, four security headers, the viewport tag, robots.txt and noindex, the status of a missing page, and first-response time.&lt;/p&gt;

&lt;h3&gt;
  
  
  What this data cannot tell you
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The scanner never logs in. Signup, password reset, one user reading another user's rows, checkout and refunds are not measured here.&lt;/li&gt;
&lt;li&gt;It does not run JavaScript. It reads the server HTML and up to 8 script files referenced from the home page, so a key in a lazily loaded chunk would be missed.&lt;/li&gt;
&lt;li&gt;Headers are read from the home page only. A CSP set through a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag is counted as missing.&lt;/li&gt;
&lt;li&gt;DKIM cannot be confirmed from outside (the selector is provider-specific), so there is no DKIM number here.&lt;/li&gt;
&lt;li&gt;The sample is a directory of projects whose makers chose to list them, not a random sample of every Lovable app.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. 189 of 190 had at least one flagged issue
&lt;/h2&gt;

&lt;p&gt;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: configuration defaults nobody revisited, not code bugs. "99% have issues" does not mean 99% are broken for users; it means almost nobody went back over the defaults.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. 94% send no Content-Security-Policy
&lt;/h2&gt;

&lt;p&gt;179 of 190 apps send no Content-Security-Policy header. CSP tells the browser which scripts may run on your page. Without it, any injected script (a compromised third-party widget, or unescaped user content) runs with full access to the page, including whatever the logged-in user can see.&lt;/p&gt;

&lt;p&gt;It is a hosting or proxy setting, not app code, which is why it is missing almost everywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check yours in 2 minutes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://yourapp.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; content-security-policy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No output means no header (or check DevTools, Network tab, first request, Response Headers). If your host does not let you set headers, a proxy in front of the domain (Cloudflare, or Netlify/Vercel header rules) can add them. Start with &lt;code&gt;Content-Security-Policy-Report-Only&lt;/code&gt; so a strict policy does not break your own scripts on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. 91% send no X-Frame-Options
&lt;/h2&gt;

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

&lt;p&gt;From the same family: 44 of 190 (23%) lack &lt;code&gt;X-Content-Type-Options: nosniff&lt;/code&gt;, and 23 of 190 (12%) lack HSTS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check yours in 2 minutes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://yourapp.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"x-frame-options|frame-ancestors"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You want &lt;code&gt;X-Frame-Options: DENY&lt;/code&gt; (or &lt;code&gt;SAMEORIGIN&lt;/code&gt;) or a CSP with &lt;code&gt;frame-ancestors 'none'&lt;/code&gt;. &lt;code&gt;frame-ancestors&lt;/code&gt; is ignored in a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; CSP tag; it only works as a response header.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. 79% return 200 for a missing page
&lt;/h2&gt;

&lt;p&gt;150 of 190 apps answered 200 OK when asked for a random URL that does not exist. It is the single-page-app default: the host serves &lt;code&gt;index.html&lt;/code&gt; for every path and the front-end router decides what to show. Visitors may see "not found", but search engines and uptime monitors see a healthy page.&lt;/p&gt;

&lt;p&gt;Search engines may index junk URLs as soft 404s, and monitors keep reporting "up" for deleted routes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check yours in 2 minutes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; https://yourapp.com/this-page-does-not-exist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it prints 200, open the 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 &lt;code&gt;&amp;lt;meta name="robots" content="noindex"&amp;gt;&lt;/code&gt;. A real 404 status needs a host-level rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. 67% have no enforcing DMARC
&lt;/h2&gt;

&lt;p&gt;127 of 190 apps have either no DMARC record at all (50) or one set to &lt;code&gt;p=none&lt;/code&gt; (77), which blocks nothing. All 127 are on their own domain: 82% of the 155 custom domains. The 35 on a platform subdomain inherit its record. And 52 custom domains (27% of all apps) have no SPF record either.&lt;/p&gt;

&lt;p&gt;Without an enforcing policy, anyone can send email as your domain, and your own signup and password-reset emails are more likely to land in spam. For the second part there is a separate guide: &lt;a href="https://shipclarity.app/lovable-password-reset-email-not-arriving.html?r=devto" rel="noopener noreferrer"&gt;Lovable password reset email not arriving&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check yours in 2 minutes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig TXT _dmarc.yourdomain.com +short          &lt;span class="c"&gt;# macOS / Linux&lt;/span&gt;
nslookup &lt;span class="nt"&gt;-type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;TXT _dmarc.yourdomain.com      &lt;span class="c"&gt;# Windows&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No answer means no record; &lt;code&gt;p=none&lt;/code&gt; is monitor-only. The target is &lt;code&gt;p=quarantine&lt;/code&gt; or &lt;code&gt;p=reject&lt;/code&gt;, but only after SPF and DKIM are set up for the provider that sends your mail, or you will block your own emails.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. 3 apps ship an API key in the bundle
&lt;/h2&gt;

&lt;p&gt;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 (&lt;code&gt;AIza...&lt;/code&gt;). This type of key is designed to sit in client code and is fine if restricted by HTTP referrer and by API in the Google Cloud console. An unrestricted one can be used on someone else's site at your expense.&lt;/p&gt;

&lt;p&gt;The more useful number is the zero: none of the 190 shipped a Supabase &lt;code&gt;service_role&lt;/code&gt; key, a Stripe live secret key (&lt;code&gt;sk_live_&lt;/code&gt;), or an AWS access key in the scanned bundles, the keys that would hand over the database or the payment account. The Supabase anon key is public by design and was not counted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check yours in 2 minutes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In DevTools on your live app, press Ctrl+Shift+F (Cmd+Option+F on a Mac) and search all loaded files for &lt;code&gt;service_role&lt;/code&gt;, &lt;code&gt;sk_live_&lt;/code&gt;, &lt;code&gt;AKIA&lt;/code&gt; and &lt;code&gt;AIza&lt;/code&gt;. A hit on the first three means rotate the key now and move the call server-side. A hit on &lt;code&gt;AIza&lt;/code&gt; means confirm in Google Cloud Console, Credentials, that the key has both a referrer and an API restriction.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. What held up
&lt;/h2&gt;

&lt;p&gt;The scary items were rare. Out of 190 apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0 exposed a &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;.git/config&lt;/code&gt;, config or backup file at a guessable path.&lt;/li&gt;
&lt;li&gt;190 load over HTTPS. 3 also still answer on plain HTTP without redirecting.&lt;/li&gt;
&lt;li&gt;140 (74%) use Supabase. For 125 of them the scanner could test the public key against the database's REST root, and none returned the schema. The other 15 could not be probed.&lt;/li&gt;
&lt;li&gt;3 publish source maps in production, 3 have the home page set to noindex, and 19 (10%) serve no robots.txt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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 each table's row-level security, testable only with two real accounts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check yours in 2 minutes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; https://yourapp.com/.env
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; http://yourapp.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first should not be 200 with real file contents (a 200 with your normal app page is the soft 404 from point 4, not a leak). The second should be a 301 or 308 redirect to HTTPS.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to take from this
&lt;/h2&gt;

&lt;p&gt;Almost everything above is configuration: headers, DNS records, a catch-all route. An afternoon covers it. None of it says whether the app works for a paying user. The failures that cost customers live behind the login: a signup that silently fails, a reset link pointing at the old preview domain, one account seeing another's data, a checkout that charges twice. This dataset cannot say how common those are.&lt;/p&gt;

&lt;p&gt;If you want to see where your own app stands, &lt;a href="https://scan.shipclarity.app/?r=devto" rel="noopener noreferrer"&gt;the free outside scanner&lt;/a&gt; runs the same 17 checks on your URL in about 20 seconds, with no signup.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>testing</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
