
Introduction to Malware Binary Triage (IMBT) Course
Looking to level up your skills? Get 10% off using coupon code: MWNEWS10 for any flavor.
Enroll Now and Save 10%: Coupon Code MWNEWS10
Note: Affiliate link – your enrollment helps support this platform at no extra cost to you.
Cyble scanned 1.3M+ newly registered domains and found AI-built sites leaking live secrets to the browser: OpenAI keys, Stripe keys, and database tokens.
Spinning up a website no longer takes a developer. A prompt to an AI app-builder returns a working, styled, deployable site in minutes, and when one template works, the same operator clones it across a dozen domains before launch. That is also how secrets end up in plain sight.
Over a month, Cyble Research and Intelligence Labs (CRIL) scanned more than 1.3 million newly registered domains, identified the ones built by AI app-builders, and read their public front-end code for exposed credentials. We built our own classifiers to spot AI-generated websites as they are registered, paired with a scanner that pulls exposed keys and credentials straight from their public code. On 35 of the 22,306 AI-built sites we identified, a genuinely private secret was sitting in the browser: live OpenAI keys, Stripe secret keys, backend database tokens, and, in several cases, a single credential cloned across a whole fleet of domains.
Thirty-five is a small number, since counting every key-shaped string on an AI-built site is easy and misleading, as most are meant to be in the browser; a single reCAPTCHA key appeared on thousands of sites. We kept only the credentials that are never supposed to leave a server. Those are the findings below.
This report walks through the two leak patterns we observed, what appears exposed, what an attacker can do with these keys, and how to shut down the exposure.
AI-built Websites are leaking the keys that power them
An AI-built site generates its content with a Large Language Model (LLM), and the key to that model often ships in the page the visitor downloads. That is the plainest pattern we found, and the most on-the-nose.
Five AI-built sites carried live OpenAI API keys in their client-side code, sixteen distinct keys across them, and four of the five are confirmed AI-generated. One AI-writing site stands out on its own: it shipped twelve different OpenAI keys, one per content category, as plain values in its bundle. Figure 1 shows a single entry, with the key masked.
A handful of sites, but each key is sensitive to exposure. An OpenAI secret key is a billing credential: anyone who reads the page can spend the owner’s balance, exhaust the rate limit, or run the bill up until someone notices and revokes it. Twelve keys in one bundle are twelve live credentials shipped at once, and five sites like this are five accounts an attacker can exploit.
Clone-and-leak: one secret across a whole fleet
An AI builder makes the hundredth site as cheap as the first, so an operator clones a working template across many domains, and whatever secret sat in the template now sits on every copy. We saw this in two shapes.
A Slack webhook shared across a 13-domain fleet. Thirteen near-identical domains, each a short word (ask, call, chat, get, hello, hey, hi, its, join, let, meet, my, see), glued to one brand, all served the same client bundle, and all embedded the same live Slack incoming-webhook URL. Figure 2 shows the URL in the shipped bundle, masked.
Anyone who can read the page can post messages to the operator’s Slack workspace via that webhook. That works for spam, for phishing aimed at the operator’s own staff, or for flooding a channel.
One Stripe secret key across four domains and two brands. A single Stripe secret key appeared on four domains under two separate brand names. The same sk_live_ value across all four points to one operator, or one shared Stripe account, behind every site. Figure 3 shows the assignment.
Figure 3 – The same live Stripe secret key reused across four domains under two brands.
A Stripe secret key provides full API access to the account, including the ability to create charges, issue refunds, and read customer and payout records. That one key exposes the operator’s whole payment account on every domain in the fleet.
The 13-domain Slack fleet runs on Bubble, a no-code and AI app builder, as confirmed by Bubble’s x-bubble-perf response header and client markers. Bubble serves each app from a dynamic.js bundle, and any value a developer places in a client-accessible field ships inside that bundle in plain text. The Stripe cluster runs on a Next.js build instead, which shows that the pattern spans builders rather than tracing to a single platform.
What else is exposed
Four AI-built sites exposed a Supabase service role JSON Web Token (JWT) on their front ends. A service-role token bypasses row-level security and grants full read and write to the project database. In terms of impact, it sits at the top of the set because it opens the entire backend rather than a single service.
Most of the remaining secret-looking strings on AI-built sites carry no/minimal exposure.
- 3,824 sites shipped browser-safe values: reCAPTCHA site keys, Stripe publishable keys, Supabase anon keys, builder telemetry tokens.
- 2,172 sites carried Google API keys, which matter only if they are unrestricted.
- 1,461 sites exposed a Supabase or Firebase backend address, which is a real exposure only when that backend’s rules are open.
Filtering those out is why the confirmed count is 35, not several thousand. Table 1 breaks the 35 down by type. The values stay withheld, and a few sites appear under more than one row.
| Exposure | Sites | What an attacker gains |
| OpenAI API key | 5 | Spend the owner’s balance, exhaust quota, run up the bill |
| Shared Slack webhook | 13 | Post arbitrary messages into the operator’s workspace |
| Stripe secret key | 6 | Full API access: charges, refunds, customer and payout data |
| Supabase service-role JWT | 4 | Full read/write to the backend database, bypassing access rules |
| AWS access key | 5 | Cloud account access, scope set by the paired secret |
| GitHub token / Google OAuth secret | 2 | Source-control or identity-provider access |
Table 1 – Confirmed private-credential exposures across 22,306 AI-built sites, by type.
What an attacker can do with these
Every credential in Table 1 is a working key to a live account. An attacker reads a public web page, copies a value, and calls an API. Here is what that buys them, key by key.
- OpenAI and other LLM keys: Run inference on the victim’s account until the bill or rate limit stops them. On a metered account, that is direct financial loss; on a funded one, it is a free, anonymous model endpoint that the attacker can point at anything, billed to the victim and running under their quota and identity.
- Stripe secret key; Drive the victim’s payment account through Stripe’s own API: create and refund charges, push the account toward fraud, and pull the customer list, email addresses, and payout history. One key is a money problem and a data-breach problem at once.
- Supabase service-role token: Read and write the entire production database, past whatever row-level security the app configured. That means stealing every user record, altering or deleting data, and planting content the app will serve back to its own visitors.
- Slack incoming webhook: Post into the operator’s own Slack as if from inside. Flooding a channel is a nuisance case; the real risk is internal phishing.
- AWS access key: With the paired secret and enough permission, reach into the owner’s cloud: spin up resources (crypto-mining is the usual first move), read storage buckets, or pivot further in.
- GitHub token or OAuth secret: Read or push to the owner’s source repositories or misuse their identity integration.
One exposure counts many times over. When the key sits on a cloned fleet, it is live on every domain in that fleet, so an attacker who finds it on one site has compromised all of them.
Conclusion
AI app-builders made it almost free to publish a website, and just as free to clone one, and most of what they produce is worth nothing to steal.
The exceptions are what we went looking for. A small, steady set of these sites hand over the key that runs them, and when an operator copies one site across a fleet, the leak rides along to every domain.
Against the millions of domains registered each month, the number is tiny, but every hit is a live account an attacker can reach and exploit just by opening the page.
If you build on these tools, read your own shipped code before you publish it. If you defend an organization, assume your keys may surface on sites you never built and look for them.
Cyble’s Threat Intelligence Platforms continuously monitor emerging threats, infrastructure, and activity across the dark web, deep web, and open sources. This proactive intelligence empowers organizations with early detection, impersonation, infrastructure mapping, and attribution insights. Altogether, these capabilities provide a critical head start in mitigating and responding to evolving cyber threats.
Our Recommendations
For developers and AI-builder users:
- Keep every secret key (OpenAI sk-, Stripe sk_live_, a Supabase service-role token) in a server-side function or backend workflow, never in a client-accessible field.
- Use only the browser-safe variants on the front end, publishable and anon keys, and enforce access with Supabase row-level security, Firebase rules, and API key restrictions.
- Rotate any key that has ever sat on the client side, and treat it as already compromised.
- Read your own page source before you ship, and search it for sk-, sk_live_, service_role, and hooks.slack.com. If you find them, so can anyone.
For SOCs and defenders:
- Monitor public code and newly registered domains for your own keys and webhooks; don’t just paste sites.
- Treat a secret found on one domain of a template fleet as exposed on all of them, and scope the response to the fleet, not the domain.
The post The Keys Are in the Browser: Secret Exposure Across AI-Built Websites appeared first on Cyble.
Article Link: Keys Are In The Browser: Exposure Across AI-Built Websites