Milo Kits
Guide

Lovable's security scan vs an outside check: what each one sees

Lovable's built-in scans look at your project from the inside: the Quick scan checks database rules, npm dependencies and exposed MCP servers on every publish, and the Deep scan reviews your code on demand. An outside check looks at what your published app hands to any stranger: the live JavaScript bundle, source maps, stray files, security headers, public storage links and whether live routes ask for a login. They answer different questions, so the safest launch uses both.

The short version

What Lovable's scan covers (from Lovable's own docs)

This section follows Lovable's security overview as it read on 19 October 2026. Lovable changes quickly, so check the docs for the current list.

Quick scan. Runs automatically every time you publish and finishes in seconds. It covers:

Deep scan. Runs on demand (it doesn't run automatically as you work) and reviews all your application code. On top of the quick checks, it looks for users who can see or change data that isn't theirs, endpoints anyone can trigger, unsafe input reaching queries or prompts, secrets in your source code or repository, payment logic a customer can bypass, weak sign-in and recovery flows, and error messages that reveal too much.

Extras. Workspaces can connect Wiz for extra code and dependency scanning, or Aikido for an AI penetration test that actively tests the running app using your repository and a test login (Lovable's Aikido docs). There's also an optional Trust center, off by default, where Lovable publishes facts it observes on your live app, such as the HTTPS redirect and security headers. It only lists checks that pass.

Two things worth knowing: Lovable says running the Quick and Deep scans is free, and that these tools "do not replace a thorough security review". That's a fair, honest description, and it's why an outside look is a useful second step rather than a replacement.

What an outside check sees

An outside check uses only what a stranger with a browser gets. No code, no login, no account on your platform. It can see:

What it can't see: your code, logic inside logged-in areas, or anything that needs an account. That's where the Deep scan and a pentest are stronger.

Side by side

QuestionLovable Quick scanLovable Deep scanOutside check
Are RLS and database rules set?YesYesSees the result: does a table answer a logged-out visitor?
Known-vulnerable npm packages?Yes (critical only)YesNo
Logic bugs: can users reach data that isn't theirs?NoYes, from the codeOnly what shows from logged-out pages and routes
Secrets in source code or repo?NoYesOnly secrets that reached the live HTML or JavaScript
What's in the shipped JS bundle?Not listedReads the source it's built fromYes, the actual shipped file
Source maps and stray files on the server?Not listedNot listedYes
Security headers (HSTS, CSP, framing)?Not listed (the opt-in Trust center reports passing ones)Not listedYes
Public storage links and bucket listing?Storage rulesStorage rulesWhether the links really open for anyone
Do live routes ask for a login?Only unauthenticated MCP serversYes, from the codeYes, by opening them logged out

"Not listed" means the item isn't in the scan's coverage list in Lovable's docs on 19 October 2026. It doesn't mean Lovable never catches it.

Why the two views disagree

The code and the live app aren't always the same thing. A setting changed in a dashboard, a file uploaded by hand, an old build still being served or a host with its own config can all make the live app differ from what a code scan reads. Code-level findings need the live view too. A vendor study by VibeRaven read the Supabase migration files of 512 public Lovable repos on GitHub in October 2026 and reported that 16.2% had a policy letting signed-out visitors update or delete every row of a table. VibeRaven notes it read code, not live databases, so it can't say which of those tables are open right now (VibeRaven, vendor research). The inside view tells you what the code says; the outside view tells you what a stranger actually gets.

Five outside checks you can do yourself

Do these on your own app only, in a private browser window so you're logged out. All of them just read what the site already sends.

1. Search the live JavaScript for secret keys

Open your app, then DevTools (F12) → Sources (Chrome) or Debugger (Firefox). Search across all files (Ctrl+Shift+F, or Cmd+Option+F on a Mac) for sk_live, sk-, service_role, sb_secret_ and secret. The Supabase URL and publishable or anon key are meant to be public; a secret key isn't. More detail in our API keys in the frontend guide.

Fix prompt: move a secret out of the browser
My live JavaScript bundle contains a secret key for [SERVICE]. Move every call that uses it into a server-side function (an Edge Function in Lovable), store the key in Secrets, not in .env or a VITE_ variable, and call that function from the frontend instead. Then tell me how to confirm the key no longer appears in the built JavaScript. I'll rotate the old key at [SERVICE] myself.

2. Look for source maps

In DevTools → Network, reload and click your main .js file. Scroll to the very end: a line like //# sourceMappingURL=index-abc123.js.map means a map is advertised. Also try opening the same file URL with .map added. If it downloads readable source code, your original code is public. Vite's default is no production source maps (Vite docs), so a map usually means someone turned them on.

Fix prompt: turn off public source maps
Make sure my production build doesn't publish source maps. Check vite.config (build.sourcemap) and any plugin that turns them on, and set it to false for production. After the next publish, tell me how to confirm that my main JavaScript file has no sourceMappingURL comment and that the .map URL no longer returns code.

3. Try a few files that should never be public

Open /.env, /.git/config and /backup.zip on your live domain. Many app hosts return your normal home page for unknown paths, which is fine. Worry only if you see file contents, such as KEY=value lines or [core].

Fix prompt: remove exposed files
On my live site, [PATH] returns file contents instead of my app. Find out why that file is in the published output, remove it from the build, and make sure .env files, .git folders and backups can never be copied into the public folder. If the file contained keys or passwords, list them so I can rotate each one.

4. Check your security headers

Run our free instant header check on your homepage, or run curl -I https://your-app.com and look for strict-transport-security, content-security-policy, x-frame-options (or frame-ancestors in the CSP) and x-content-type-options. Missing headers rarely leak data on their own, but they're quick wins.

Fix prompt: add security headers
My app is hosted on [HOST]. Tell me whether I can set custom response headers there, and if so add: Strict-Transport-Security (max-age=31536000), X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, X-Frame-Options: DENY, and a Content-Security-Policy that starts in Report-Only mode so nothing breaks. List every external domain my app loads scripts, styles or data from so the CSP allows them.

If you host on Netlify or Vercel, our security headers guide has copy-paste configs.

5. Open your private pages, API routes and file links while logged out

Logged in, in a normal window, note the URLs of your admin page, dashboard, one API call from the Network tab, and one private file (an uploaded invoice or avatar). Now paste each one into the private window. A login screen or an error is good. Seeing the page, the JSON data or the file means the login only hides the button. For your database tables, our Supabase anon key guide shows the logged-out test.

Fix prompt: enforce login on the server
When I'm logged out, these still return data: [LIST THE URLS]. For each one, enforce the check on the server, not just in the UI: Edge Functions and API routes must verify the user's session and their role or ownership before returning anything, database tables need RLS policies that limit rows to their owner, and private files should live in a private storage bucket served through short-lived signed URLs. Show me how to repeat my logged-out test to confirm each fix.

A simple routine that uses both

  1. Before you publish, let the Quick scan run and fix its critical findings.
  2. Before a real launch, or after big changes to sign-in, data or payments, run the Deep scan from the Security view.
  3. After publishing, do the five outside checks above on the live URL.
  4. If you handle sensitive data or payments, consider a pentest or a human review as well.

Our free pre-launch checklist puts these into 14 checks with a prompt for each.

FAQ

Is Lovable's security scan enough before launch?

It's a strong first step, and Lovable itself says its scans don't replace a thorough security review. Run the Quick and Deep scans and fix what they find. Then look at the live app from the outside: what's in the JavaScript bundle, whether source maps or files are reachable, which security headers are set, and whether your pages and API routes ask for a login when you open them logged out.

Does Lovable check security headers?

Headers aren't in the Quick or Deep scan lists in Lovable's security docs. The optional Trust center, which is off by default, reports HTTPS, HSTS and browser-protection headers it observes on your live app, but it only lists checks that pass. You can check headers yourself with any header checker or with curl -I.

Is the Supabase key in my Lovable bundle a leak?

Usually not. Lovable's docs say VITE_ values such as VITE_SUPABASE_URL and VITE_SUPABASE_PUBLISHABLE_KEY are built into the browser bundle and are meant to be public. What matters is that every table has row-level security with the right policies. A service_role or sb_secret_ key in the bundle is a real leak: rotate it.

What does an Aikido pentest add on top of Lovable's scans?

According to Lovable's docs, an Aikido pentest is dynamic: AI agents interact with your running app, send real payloads and test sign-in and access flows, using your repository and a test login you provide. Lovable recommends running its own scans first, fixing those, then validating with a pentest. It's billed by Aikido.

Can I run these outside checks on someone else's app?

Only on apps you own or have permission to test. Everything in this guide is read-only: opening pages, reading what your browser already downloaded and looking at response headers. Don't try passwords, change data or test someone else's site.

Sources

This guide is general information, not a security audit. Lovable's descriptions are summarised from its public docs as of 19 October 2026; platforms change, so check the linked docs for current details. Spotted something out of date? Email hello@milokits.com.

More guides