Guide

What can a stranger see in your app?

Checked on 1 November 2026

Short answer

A stranger who opens your web app can see everything their browser downloads: all of the app’s code, the address of your database and of every service the app calls, every key written into that code, and every answer those services send back.

This is safe only when the code holds no secret keys and every database table has access rules, so look at your own app with the browser’s developer tools, move any secret key to a server function, and turn on row level security (the database’s access rules) for every table.

LidTight’s free check does the same outside look in seconds. On Tidybook, our demo app built with Lovable, it found no secret keys, but a reviews table that anyone could read: 12 rows, with email and phone columns.

1.Everything the browser downloads is public

A web app works by sending code to the visitor’s browser, which runs it. Lovable’s docs say it plainly: the frontend code it generates runs in the browser, so API keys and other secrets cannot be stored safely in it.

Anything the browser receives, a visitor can read. That includes:

  • The app’s code: every JavaScript file. Minified code (with spaces removed and names shortened) is not hidden: developer tools add the spacing back to make it easier to read.
  • Page names, such as /admin, because the code must know every page it can show.
  • The addresses the app calls: your database, your server functions, and services for payments or email.
  • Public keys: the keys the app sends with its calls, such as a Supabase publishable key.
  • Every answer: all that the app’s calls bring back, including fields the page does not show.
  • Your original source code, if the app publishes source maps (files that map the squeezed code back to the code as written). The Vite build tool makes none by default.

None of this needs a hack. The browser must receive it to run your app, so treat all of it as public.

2.What is fine to be public, and what is not

Public does not mean unsafe. Some things are meant to be seen. Others give a stranger power over your money or your customers’ data.

ItemPublic?Why
Your database addressFineThe browser needs it. Access rules, not the address, protect the data.
Supabase publishable key (sb_publishable_…) or the older anon keyFineSupabase calls it safe to expose: it only reaches what row level security allows.
Stripe publishable key (pk_…)FineStripe says only publishable keys are safe to expose outside your backend.
Page names, such as /adminFineA page name is not a lock. The server must decide who may load the data behind it.
Supabase secret key (sb_secret_…) or the older service_role keyNeverIt bypasses every row level security rule you have.
Stripe secret and restricted keys (sk_…, rk_…)NeverStripe makes you responsible for protecting every key except the publishable one.
AI and email service keys, such as OPENAI_API_KEY or RESEND_API_KEYNeverLovable lists them as backend secrets that must never reach the browser (if one leaked).
Customer data (emails, phones, orders)Only to its ownerEach table needs rules that decide who may read and change each row.

3.What a stranger can do when a table has no access rules

Supabase creates a web API from your tables, so the browser can read and write them directly. Lovable’s built-in backend (Lovable Cloud) is built on Supabase.

Row level security (RLS) is the set of rules inside the database that decides which rows each user may read or change. Supabase warns that a table without RLS can be read and changed by every kind of caller that has permission on it. On projects that still give signed-out visitors every grant by default, a stranger with your database address and your public key can:

  • read every row of that table, without signing in;
  • add, change or delete rows in it;
  • see the names of your tables and columns, because the API describes itself to any caller with permission on them, even when RLS is on.

With RLS on and no rules yet, the public key reads nothing: Supabase says no data is accessible through the API until you create rules. Table names on their own are not a leak. Rows of customer data are. See also your Supabase public key and Base44 app security.

4.Example: what LidTight’s free check saw on Tidybook

On 1 November 2026 we ran LidTight’s free check on Tidybook, our own demo app built with Lovable. Like any stranger, the check opened the app signed out and read only what any visitor’s browser can see.

What the check looked atWhat it found
The code visitors download27 files, 738 KB
Secret keys in that codeNone found
The databaseLovable Cloud (Supabase), 1 server function and 2 tables: bookings and reviews. The database listed its tables and their columns.
Pages named in the codeAn admin page, /admin. Anyone can see that it exists.
Tables a stranger can readCritical: the reviews table, 12 rows, with first_name, email and phone columns. No sign-in needed.
Sign-up settingsHigh: anyone can create accounts without confirming an email (what that means)
Files that should not be public, and source codeNone found. Source code not public.

The admin page name is normal; what matters is whether the server refuses its data to non-admins. The real problem is the reviews table, with the columns id, first_name, last_initial, email, phone, rating, text and created_at. In the check’s words, “A stranger can download these records with one request.”

The check counted the 12 rows with a request that returns only a number. To confirm that the first_name, email and phone columns hold real values, it read those three columns from a few rows and kept none of the values. The free check cannot see what a signed-in user can reach or change; our deep checks test that with two test users.

5.How to look at your own app

These steps use Chrome; Firefox has a similar Network Monitor.

  1. Sign out of your app, then open its live address in Chrome.
  2. Open the developer tools: press F12 or Ctrl+Shift+I on Windows, or Cmd+Option+I on a Mac (Chrome docs). Click the Network tab and reload the page, because the tools only record what happens while they are open.
  3. Click Fetch/XHR to show only the data calls. Calls to /rest/v1/ go to your Supabase database. Click one and open its Response tab to see everything that came back.
  4. Open every page you can reach without signing in, and read the responses. If one holds other people’s emails, phones or orders, a stranger can read them too.
  5. Search everything the page loaded: in the Network tab, press Ctrl+F (Windows) or Cmd+F (Mac) to search all requests and responses. Search for sb_secret_, sk_live_, sk_test_, rk_live_ and the start of every other secret key you own. Any match is a leaked secret. Older Supabase keys start with eyJ: only the anon one is fine, so compare each one with the keys in your Supabase settings.
  6. Open the Sources tab, then its Page tab, to see every file the page loaded. Look for page names such as admin. If you also see your own original files, the app publishes source maps.
  7. Check the access rules from the inside. In Lovable, review your rules under More → Database → Manage → Policies, and run the Quick scan from the Security view (Lovable docs). On your own Supabase project, open the Security Advisor and fix every “RLS disabled in public” warning.

Do these steps only on apps you own or run. On your own app they are safe: you only read what your browser has already received.

6.What your builder hides, and what it cannot hide

A builder can keep a secret key out of the browser only if the key never enters the page code. Lovable keeps keys in Secrets: encrypted, given to server functions, never sent to the browser. Its safe pattern: store the key in Secrets, make the call in server-side code, and call that code from the page.

No builder can hide the code that runs in the page. Lovable builds values named VITE_…, such as the database address and the publishable key, into the code the browser downloads, and the Vite docs warn that such values should not hold sensitive information. Lovable also says frontend code can be inspected, modified or bypassed, so a hidden button or a check in the page stops no one.

Builder scans help. Lovable’s Quick scan runs each time you publish and flags tables without per-record access control. It checks your database rules and settings from the inside; an outside check shows what a stranger actually gets back. See Is your AI builder’s own scan enough?

What to fix first

  1. Move every secret key out of the page code into your builder’s secrets store, and call the service from a server function.
  2. Make a new key at the service that issued it, and delete the old one: Lovable says a secret in frontend code should be considered compromised.
  3. Turn on RLS for every table, with a rule for who may read and who may change each one. Then repeat the steps above, signed out, to confirm.
  4. Check admin rights, plans and prices on the server, never only in the page. See Can users get your paid features for free?

Before you go live, see the full launch security checklist.

Sources

  1. Lovable docs: Security overviewdocs.lovable.dev
  2. Lovable docs: Secretsdocs.lovable.dev
  3. Lovable docs: Security best practices for Lovable appsdocs.lovable.dev
  4. Lovable docs: Built-in backenddocs.lovable.dev
  5. Supabase docs: API keyssupabase.com
  6. Supabase docs: Row Level Securitysupabase.com
  7. Supabase docs: Data REST APIsupabase.com
  8. Supabase docs: Advisorssupabase.com
  9. PostgREST docs: OpenAPIdocs.postgrest.org
  10. Stripe docs: API keysdocs.stripe.com
  11. Vite docs: Env Variables and Modesvite.dev
  12. Vite docs: Build Options (build.sourcemap)vite.dev
  13. MDN: Minificationdeveloper.mozilla.org
  14. MDN: Source mapdeveloper.mozilla.org
  15. Chrome DevTools: Open Chrome DevToolsdeveloper.chrome.com
  16. Chrome DevTools: Inspect network activitydeveloper.chrome.com
  17. Chrome DevTools: Network features referencedeveloper.chrome.com
  18. Chrome DevTools: Sources panel overviewdeveloper.chrome.com
  19. Firefox DevTools: Network Monitorfirefox-source-docs.mozilla.org