For apps built on Replit · Lovable · Bolt · vibe coded
The secret key your app uses in the browser is in every visitor's browser too.
You built something people use, and some of it talks to OpenAI, Stripe or your database straight from the front end. If that code holds a secret key (an AI key, a payment secret, the database's admin key), the key is part of the page. Anyone can read it, with no login and no trace.
Paste the address. Nothing to install, works on your phone.
1 · How it happens
One prefix decides who gets the key.
Vite puts every variable starting with VITE_ that your code reads into the JavaScript it ships. Next.js does the same with NEXT_PUBLIC_, Create React App with REACT_APP_, Expo with EXPO_PUBLIC_. When the code that calls an AI model, a payment provider or the database's admin client runs in the browser, its key has to be there too: under one of those names, or pasted straight into the source. The build succeeds, the feature works, and the key is part of the page.
2 · What it costs
Whatever the key can do, anyone can do.
A Supabase service-role key reads and writes every row in your database with no policy applying. An OpenAI or Anthropic key runs requests that are billed to your account. A Stripe secret key reads your customers and can issue refunds. None of it needs a password and none of it shows up as a login in your app. To every system involved, it looks like you.
3 · Why you haven't seen it
Nothing is broken, so nothing warns you.
A leaked key is a key that works. The app runs, the tests pass, your own requests look exactly like a stranger's. Nobody has to break in: the key is in files every visitor downloads, and key-shaped strings are easy to search for. The first sign is usually a bill, a quota email, or rows that changed when nobody on your side changed them.
What the free check shows you
Findings like these, for every gap in your app: how serious it is, what is wrong, where it is, and what it costs you if it stays.
2 secret-shaped values are declared under a client-public environment prefix: VITE_SUPABASE_SERVICE_ROLE_KEY, VITE_OPENAI_API_KEY.
Anything on that prefix is compiled into the JavaScript the browser downloads, so the key is public the moment the site is: readable by viewing source, with no breach, no login and no trace. A service-role database key exposed this way grants full read and write over every customer's data.
Evidence.env.example:3
VITE_SUPABASE_SERVICE_ROLE_KEY, a credential that bypasses row-level security, is referenced at src/integrations/supabase/admin.ts:9, inside code that ships to the browser.
Anyone who opens the site can read it out of the bundle and then read and write every row in every table directly, with no account, no policy applying and no trace in the application's own logs.
Evidencesrc/integrations/supabase/admin.ts:9
Run the free check tonight.
Paste your app's address. See what every visitor can already read. Nothing to install.
The full check runs in your coding tool, on your machine, in a few minutes. What reaches us: counts, rule names and file paths with line numbers. Never your source, your data or a secret value. Your report page is kept 7 days behind an access code. Exactly what it runs →
Add it, sign in, ask.
claude mcp add --transport http prodready https://mcp.prodready.si/mcp --scope user- Add it. Run it in a terminal.
- Sign in. In Claude Code type
/mcp, pick prodready, choose Authenticate. A browser page asks for your email; type the 6-digit code we send (or click its link), then approve. No password, no card. - Ask. Type “check my app”.
Send it to your laptop.
After the report: when you want the gaps closed the way serious software teams close them, the same prodready connection runs the SDLC on your project. How that works →