Everything in a browser bundle or mobile app is public, including any variable your framework inlines at build time. Which keys are designed to be public and what actually protects you when they are, which must never ship, and what to do in the first hour after one leaks.
Framework conventions make the line easy to cross. Vite exposes any variable prefixed VITE_ to client code and warns that these "should not contain sensitive information such as API keys". Next.js inlines NEXT_PUBLIC_ variables into the JavaScript bundle at build time. A secret behind either prefix is published to every visitor.
Book a free 30-minute call. You'll leave knowing what we'd do first and roughly what it costs, whether or not you hire us.
Build the app and search the output for key prefixes (sk_, sk-, sb_secret_, service_role, AKIA) and the names of your secret variables.
Open the deployed site, look at the loaded JavaScript in developer tools, and search for the same strings.
Search the repository history, not just current files. Deleted secrets live on in old commits, forks and clones.
Turn on GitHub secret scanning and push protection. They are on by default for new public repositories owned by personal accounts; private and organization repositories need them switched on.
Rotate first: issue a new key, deploy it, revoke the old one. Investigate second.
Check the provider's usage and billing for activity you did not cause. Leaked model keys tend to be used quickly.
Remove it from the code. If the repository was public, rewriting history does not make the key secret again.
Add a check so it cannot happen the same way twice: push protection, a CI step that scans the build output, or both.
Once a month: what changed in tech that month and what it means for you, from cloud and AI to security and the tools you build with. Every item links to its source. No sales pitch, unsubscribe in one click.
Book a free 30-minute call about it. Bring your setup and your bill; you'll leave knowing what we'd do first and roughly what it costs, whether or not you hire us.
Or keep reading
Row-Level Security: The Check Between Your Users' Data and Everyone Else
Apps on Supabase, Firebase and similar platforms let the browser talk to the database directly. That is fine only if the database enforces who sees what, because anyone can call the same API without your UI. How row-level security works, the gaps that catch people (views, functions, storage), and a ten-minute test.
Read
File Uploads Done Right: Presigned URLs, Limits, and Not Proxying Through Your Server
Uploading through your API runs into payload limits (6 MB for synchronous Lambda, 10 MB for API Gateway), ties up servers and pays for the bytes twice. Letting the browser upload straight to S3 with a presigned URL avoids all three. How it works, enforcing size and type, scanning for malware, and serving files back privately.
Read
As of October 26, 2026. Provided as is, for general information, and accurate to the best of our knowledge on the date shown. Not legal, compliance, tax, financial or other professional advice. Prices, limits and vendor services change; check current vendor documentation before relying on anything here. Terms of use.