Anything in the JavaScript a browser downloads is readable by anyone who downloads it. That is not a vulnerability; it is how the web works. The failure is putting a key there that can do more than the anonymous role.
The numbers
GitGuardian counted 28.65 million new hardcoded secrets pushed to public GitHub in 2025, a 34% rise year over year. (Source: GitGuardian, 2026-03-17 · verified 2026-09-21) The same report measured a 3.2% secret-leak rate in commits co-authored with one AI assistant against a 1.5% baseline, and noted that the developer still accepts each suggestion. (Source: GitGuardian, 2026-03-17 · verified 2026-09-21; denominator: public GitHub commits carrying that assistant's co-author trailer, against all public GitHub commits in 2025) Escape's scan of 5,600 prompt-built apps found more than 400 exposed secrets. (Source: Escape, 2025-10-29 · verified 2026-09-21)
Why the framework does not save you
Next.js exposes any environment variable prefixed NEXT_PUBLIC_ to the client, and keeps everything else on the server. (Source: Next.js docs, 2026-08-25 · verified 2026-09-21) Expo does the same with EXPO_PUBLIC_. The prefix is the contract. Generated code copies the prefix from the variable next to it, because that is what makes the value available where the code is being written, and the value it copies can be a service-role key.
In a React Native app there is no server side at all: the docs say anything in the app code can be read from the bundle (the JavaScript your app sends to the browser or ships inside the mobile app; anyone can read it), and that .env tools are not server-side environment variables.
The item
SC-01 scans the built client assets, not the source, for two things: known key prefixes (sk_, rk_, service_role, AKIA, whsec_, private key headers) and every value present in the server environment file. The second check is the one that matters, because a key without a recognisable prefix still leaks. Pass is zero matches.
SC-03 is the manual companion: list every client-prefixed variable and confirm each one is meant to be public. SC-02 scans the git history, because a key removed from the file is still in the repository.
After a finding
Rotate first, then fix. A key in a deployed bundle has been public since the deploy, and removing it from the next build does not revoke it. The record for a SC-01 finding includes the rotation timestamp.
The secrets category has all five items. The Next.js, Expo and React Native hubs list the vendor defaults that make each one necessary.