what we check

Every check, in plain words.

47 checks across your live app and your code. Each one says what it means for you first. The ids on the right are what you will see on a finding, if you want to look one up. Every finding in the app also comes with a fix prompt for your builder.

live app scan

Live app scan

What a stranger with a browser can see on your live app: the pages and JavaScript it sends, how it is served, and its HTTPS setup. Runs against the exact address you verified.

live app scan · secrets

Keys in your JavaScript

Everything in your app's JavaScript is downloaded by every visitor. If a secret key ends up in there, it is not secret any more. We look for real, usable keys from dozens of providers and show them redacted (like sk-proj-Ab…9xQ). Keys that are meant to be public, like the Supabase anon key or the Firebase web config, are not treated as leaks.

high

An AI provider key anyone can copy

Anyone can lift the key from your page and run up your AI bill. The fix is to call the AI from a server function instead of the browser, then rotate the key.

secrets.openai-key
secrets.anthropic-key
secrets.google-ai-key
secrets.groq-key
secrets.openrouter-key
critical

Your Supabase master key is in the browser

This key skips every access rule in your database. In the browser it means anyone can read, change or delete all of your data.

secrets.supabase-service-role
secrets.supabase-secret-key
critical

Your Stripe secret is public

With it, someone can read your customers, issue refunds or create charges on your account.

secrets.stripe-secret-key
secrets.stripe-webhook-secret
high

Other server keys

AWS, GitHub, Resend, SendGrid, Twilio, Slack, database connection strings and more. Each one is a door into a service you pay for.

secrets.<key-type>
high

A secret-sounding setting built into the page

Build tools copy every VITE_, NEXT_PUBLIC_, REACT_APP_ and EXPO_PUBLIC_ variable into the JavaScript. A setting called something like VITE_STRIPE_SECRET is public, whatever is in it.

secrets.public-env-secret
live app scan · platform

AI called from the browser

We work out which builder and stack made your app (that is how fix prompts get worded for it), and look at how it talks to AI providers.

high

The OpenAI or Anthropic SDK runs in the browser

The code turns on a setting literally named dangerouslyAllowBrowser. It means your AI key travels to every visitor, where anyone can copy it.

platform.ai-sdk-in-browser
info

The browser talks to an AI provider directly

Only safe if each visitor brings their own key. If the app uses yours, it is in the page or fetched at runtime, and either way it can be copied.

platform.ai-api-called-from-browser
live app scan · headers

Browser safety settings

Response headers tell browsers how careful to be with your site. Missing ones are rarely an emergency, and most builders can add them in one prompt.

medium

Your server tells browsers any website may read it

Fine for truly public data. A problem if your API returns anything private, and worse if it also tries to allow your users' cookies.

headers.cors-wildcard-credentials
headers.cors-wildcard
medium

Plain http:// is not sent to https://

Visitors who type your address without https stay on an unencrypted connection.

headers.no-https-redirect
low

Browsers are not told to always use HTTPS

HSTS makes browsers refuse the unencrypted version of your site, even on sketchy Wi-Fi.

headers.missing-hsts
headers.weak-hsts
low

No Content Security Policy

A CSP limits which scripts may run on your pages, which blunts the damage if someone manages to inject one.

headers.missing-csp
low

Your app can be framed by other sites

Another site could load yours invisibly and trick people into clicking buttons in it.

headers.clickjacking
low

Browsers may guess file types

Without nosniff, a browser can treat an uploaded file as a script.

headers.missing-nosniff
low

Full page addresses leak to other sites

Links out of your app can send the full URL, including any tokens in it, to the site you link to.

headers.missing-referrer-policy
info

Your server announces its exact version

It makes looking up known bugs for that version a little too easy.

headers.server-version-disclosure
info

No way for researchers to reach you

A security.txt file tells people who find a problem where to report it. Custom domains only.

headers.missing-security-txt
headers.security-txt-expired
live app scan · tls

Your HTTPS certificate

Platform addresses like lovable.app or replit.app handle this for you. On a custom domain it is worth a look.

high

Certificate expired or about to

When it lapses, browsers show a full-page warning and most visitors leave.

tls.cert-expired
tls.cert-expiring
tls.cert-expiring-soon
tls.renewal-stalled
high

Certificate not trusted for this address

Browsers will warn visitors that the connection may not be private.

tls.untrusted-cert
tls.hostname-mismatch
medium

Old encryption still accepted

TLS 1.0 and 1.1 are retired. Only very old devices need them.

tls.tls10-enabled
tls.tls11-enabled
tls.weak-negotiated-protocol
medium

Weak certificate key or signature

The certificate uses cryptography that is no longer considered strong.

tls.weak-key
tls.weak-signature
live app scan · web

Pages and forms

We crawl a handful of pages on your app (same address only) and look at forms and the scripts they load.

high

A form sends data unencrypted

Passwords or personal details typed into the form travel over plain http.

web.login-form-http
web.pii-form-http
web.form-posts-http
medium

Secure pages load insecure files

An https page pulls in scripts or images over http, which someone on the network could swap out.

web.mixed-content
low

Outside scripts loaded without a fingerprint

If that CDN is ever compromised, the altered script runs in your app.

web.third-party-script-no-sri
low

Tracking cookies before consent

Analytics or ad cookies are set before the visitor agrees, which matters if you have visitors in the EU or UK.

web.tracking-cookie-before-consent
live app scan · exposure

Files that should never be public

Asking your live app for a short list of files that should not be served: .env, the .git folder, source maps, platform config.

critical

Downloadable .env, .git and source maps

A single request to your live app is enough for anyone to download these. We check a fixed list of paths and confirm the content is real, not your app's catch-all page.

exposure.env-file
exposure.git-directory
exposure.source-maps
live app scan · api

CORS on your live API

Testing, with plain GET requests, whether your live API lets any other website use your visitors' logged-in sessions.

high

CORS that lets any site use your users' sessions

If your API echoes back whatever website asks and allows cookies, a malicious page can read private data as whoever is logged in.

api.cors-reflects-origin-with-credentials
api.cors-allows-null-origin

repo scan

Repo scan

What is inside your code on GitHub, read through our GitHub App and never run. On demand, and on paid plans on every push.

repo scan · repo-secrets

Secrets committed to your code

Builders that sync to GitHub (Lovable, Replit, Bolt) and editors like Cursor commit whatever is in the project. If a key was pasted into a file, it is in the repo, and everyone with access to the repo has it.

high

A live secret key in a source file

We show the file and line, with the key redacted, so you know exactly which key to rotate. Keys in browser code are ranked higher than keys in server code.

repo-secrets.<key-type>
critical

A .env file is committed

The file that is supposed to stay on your machine (or in your platform's Secrets pane) is in the repository.

repo-secrets.env-file
repo scan · repo-deps

Packages with known holes

Your app is built on hundreds of open source packages. We read your lockfile (npm, pnpm, Yarn, Bun, Poetry and more) and look each version up in OSV.dev, the open vulnerability database.

medium

A package you use has a published vulnerability

We name the package, the version you have and the version that fixes it. One upgrade that clears several advisories counts as one problem.

repo-deps.<ecosystem>-<package>-<version>
low

No lockfile

Without one, each install can pull different versions, and we cannot tell which ones you actually run.

repo-deps.no-lockfile
repo scan · repo-rules

Database rules in your repo

Supabase migrations and Firebase rules files decide who can read your data. We read them in the repo, so a table with no access rules is caught in the code, before it is deployed.

critical

Tables without Row Level Security

A migration creates a table and never turns RLS on, so your app's public Supabase key can read and change it as soon as the migration runs.

repo-rules.rls-disabled
high

Policies that let everyone in

RLS is on, but a policy like using (true) means anyone can read, add, change or delete rows anyway.

repo-rules.policy-anyone-can-write
repo-rules.policy-anyone-can-insert
repo-rules.policy-anyone-can-read
high

Database views that skip RLS

A view runs with its creator's rights, so it can show rows the table itself would hide.

repo-rules.view-bypasses-rls
medium

Extra permissions handed out

A GRANT that opens a table to anonymous visitors, or a privileged function that can be tricked into running someone else's code.

repo-rules.grant-to-anon
repo-rules.security-definer-search-path
critical

Firebase rules open to everyone

Your firestore.rules, storage.rules or database.rules.json let anyone read or write without signing in.

repo-rules.firebase-open-firestore
repo-rules.firebase-open-storage
repo-rules.firebase-open-rtdb
high

Firebase rules still in test mode, or too generous

Test-mode rules, parts of the database anyone can change, or rules where any signed-in user can change everything.

repo-rules.firebase-test-mode-<service>
repo-rules.firebase-open-write-<service>
repo-rules.firebase-any-user-<service>
repo scan · repo-code

Risky code patterns

Patterns that AI-written code gets wrong often, in JavaScript, TypeScript and Python. Some are hints for a human (or your AI) to look at, and say so.

critical

Supabase master key used in browser code

Front-end code creates a Supabase client with the service_role key, which ignores every access rule.

repo-code.service-role-in-client
high

Secrets or AI keys wired into the browser

A secret read from a VITE_ or NEXT_PUBLIC_ variable, or an AI SDK told to run in the browser.

repo-code.secret-in-public-env
repo-code.ai-key-in-browser
high

Admin checks that trust the browser

If "is this user an admin?" comes from localStorage, anyone can flip it in their browser's dev tools.

repo-code.client-side-role-check
high

Any website can make logged-in requests to your API

Server code like cors({ origin: true, credentials: true }) lets a page on any site call your API with your users' cookies.

repo-code.cors-any-origin-with-credentials
high

Database queries built from pasted-in text

Values are glued straight into SQL, which lets someone rewrite the query.

repo-code.sql-injection
repo-code.sql-string-building
high

Login tokens accepted without checking them

The server reads a token without verifying its signature, so anyone can forge one.

repo-code.jwt-not-verified
high

Stripe webhooks that anyone could fake

Your webhook handler does not check the request really came from Stripe, so someone could mark orders as paid.

repo-code.stripe-webhook-unverified
high

Passwords hashed with MD5 or SHA-1

If the database ever leaks, these are quick to crack.

repo-code.weak-password-hash
medium

A server route that does not check who is calling

An endpoint that changes data without looking for a signed-in user.

repo-code.route-without-auth
medium

Text turned into HTML or code without cleaning

Things like dangerouslySetInnerHTML or eval, fed with data that might come from a user.

repo-code.unsafe-html
repo-code.eval
medium

Shortcuts that weaken security

HTTPS certificate checks switched off, or Math.random used to make tokens.

repo-code.tls-verification-disabled
repo-code.insecure-random

not yet available

Coming to the live app scan

These are being built and are not part of any scan today. We list them so you know what is covered and what is not. Where the repo scan already catches the same problem in your code, we say so.

not yet available

Live Supabase checks

Checking, with your app's own public key and read-only requests, whether its Supabase tables, storage buckets and auth settings are open to anyone.

planned

Tables and buckets readable with the public key

Until this ships, the repo scan catches the usual cause: migrations that create tables without RLS.

supabase.*
not yet available

Live Firebase checks

Checking, read-only, whether your Realtime Database, Firestore and Storage answer to strangers.

planned

Open database and storage rules

Until this ships, the repo scan reads your Firebase rules files.

firebase.*

severity

How we rank things

critical

Fix today

Someone could read or change your data, or spend your money, right now, with nothing more than a browser.

medium

Fix this week

A real weakness, but it needs something else to go wrong first, or the damage is limited.

info

Good to know

Worth tidying up when you are in there. These barely move your grade.

Your grade (A to F) weighs findings by severity, so one open table outweighs a handful of missing headers, and any critical finding means an F however tidy the rest is. The same problem found in several places counts once. A clean scan means none of these checks found a problem, not that the app is perfectly secure: we see what is visible from outside and in your repo, not everything.

Run all of them on your app.

One app is free. No card.