Originally published on Sitecheckly.
In the survey, 92% of AI-built apps were missing Content-Security-Policy, 89% lacked clickjacking protection, and 55% loaded Supabase directly from the browser. Browser access to Supabase is not itself a vulnerability. These vibe coding security statistics point to header configuration gaps and a need to verify database permissions, protect secret keys, and keep sensitive instructions out of client code.
The sample covered 560 public apps that their makers listed on Made with Lovable, a showcase of apps built with Lovable. Of those, 474 served a page that could be analyzed. Because makers chose to list their apps, the sample leans toward launched projects. It does not represent every AI-built app or every Lovable project.
How do AI-built apps compare with top websites?
The average security score in the survey was 76.3 out of 100, compared with 77.1 for the Tranco top-sites survey. Those similar averages hide differences in individual checks.
| Observable finding | AI-built apps | Top sites |
|---|---|---|
| Missing Cross-Origin-Opener-Policy (COOP) | 98% | 95% |
| Missing Content-Security-Policy (CSP) | 92% | 66% |
| No clickjacking protection | 89% | 43% |
| Cookies without a SameSite attribute | 71% | 38% |
| No CAA records | 95% | 78% |
| No DMARC record | 72% | 24% |
| No SPF record | 69% | 19% |
| Third-party scripts without Subresource Integrity | 30% | 61% |
These are different kinds of findings. CAA, SPF, and DMARC all use DNS records, not HTTP response headers. CAA restricts certificate issuance, while SPF and DMARC concern email. They should not be treated as interchangeable with CSP or cookie settings. The dataset separates these observable checks; a missing control is not, by itself, proof of an exploitable app.
The comparison also runs in both directions. Third-party scripts without Subresource Integrity appeared less often in the AI-built apps than in the top-sites survey. That does not cancel out other gaps, just as missing COOP does not carry the same implications as a leaked secret key.
Use the findings as a configuration checklist:
- Configure CSP for the resources your app needs. A policy copied from another project may not fit your scripts, styles, connections, or embedded content. The MDN CSP guide explains how policies restrict resource loading and how to test a policy before enforcing it.
- Review framing protection and COOP. Choose settings for the app rather than adding headers solely to improve a score. Include these checks when you run a passive security audit.
- Review cookies and DNS separately. Set appropriate SameSite attributes for your cookies. Review CAA, SPF, and DMARC records with whoever manages your domain and email configuration.
- Add integrity hashes where suitable. Subresource Integrity lets browsers check a fetched resource against an expected hash. It is useful for suitable third-party scripts, but it is not a replacement for reviewing what those scripts do.
A good passive score is not a safety guarantee. It reflects the checks visible to the survey, not a complete assessment of application code, permissions, or runtime behavior.
Are Supabase and Firebase safe to use from the browser?
Browser SDK usage and exposed secret credentials are different findings. Treating all client-side backend configuration as a leak makes it harder to identify the problems that need attention.
Supabase
In the survey, 55% of apps (262) loaded Supabase directly from the browser. A related finding was that 52% (247) included a Supabase public anon or publishable key in page code. These figures measure different observations and should not be substituted for each other.
Public anon and publishable keys are intended for client use. Their presence is not evidence that private data is exposed. For a Supabase application, the important follow-up is to review the database authorization enforced by Row Level Security, or RLS.
As the owner, review and test your own policies:
- Confirm which tables the client needs to access.
- Check what unauthenticated visitors are permitted to do.
- Test what signed-in users can read and change.
- Confirm that requests outside those permissions are denied.
- Keep service-role keys out of shipped client code.
An outside passive scan cannot see or verify your RLS policies. Finding a public key therefore answers neither “Is the database exposed?” nor “Are the permissions correct?” Those questions require owner-side review and testing.
Firebase
The Firebase JavaScript SDK supports browser applications. Browser configuration alone is not a substitute for authorization.
For your own project, review Firebase Security Rules and test both permitted and denied access. Make the expected outcomes explicit before testing, then check that the rules enforce them.
The survey figures here do not establish a Firebase usage rate. They also do not establish whether any project's authorization rules are correct.
Do AI-built apps expose secret keys or call AI APIs directly?
In the survey, 0.2% of apps (1) shipped a secret key in their own page code. Separately, 1.7% (8) called an AI provider API directly from the browser.
Do not assume these are the same apps. A detected browser API call and a detected secret key are separate findings. The aggregates do not establish that every direct call included a secret credential.
If a secret appears in shipped client code, treat it as exposed. Removing it from the latest build is not enough to make the old credential safe again. This is a sensitive-information problem, consistent with the risks covered by the OWASP Top 10 for LLM applications.
For your own app:
- Remove the credential from client code. Check the source and the deployed JavaScript output.
- Revoke or rotate it with the provider. Do not rely on a code change alone.
- Review the provider's usage records. Investigate activity you do not recognize.
- Move calls requiring secret credentials to a server-side endpoint. Keep those credentials in server-side environment configuration.
- Apply authorization and usage limits. Treat the endpoint as part of your application's access-control boundary, not just a place to hide a key.
The practical distinction is between configuration intended to be public and credentials that grant privileged access. Fixing the latter takes priority over cosmetic changes to public configuration.
What does an exposed AI system prompt mean?
In the survey, 1.5% of apps (7) exposed an AI system prompt in JavaScript.
A prompt is not inherently a secret. Its exposure becomes more concerning when it contains credentials, sensitive instructions, or rules that the application relies on for security.
OWASP LLM07, System Prompt Leakage, warns against treating prompt confidentiality as a security boundary. Instructions telling a model not to reveal information are not a substitute for enforcing access controls in application code.
Review exposed prompts for what they contain, not just whether they exist:
- Remove credentials and other secrets.
- Enforce authorization in application code rather than relying on model instructions.
- Keep sensitive instructions out of shipped client code.
- If a prompt contained a credential, handle that credential as exposed.
For your own app, use the free system prompt leak checker as a starting point. Follow any finding with a review of the prompt's contents and the application controls around it.
How was the survey conducted, and what can it prove?
The fetch took place on 2026-11-08. Of the 560 listed apps in the sample described above, 474 returned a page that could be analyzed. The results therefore describe the analyzed pages, not every listed project or AI-built app.
The method was passive:
- Fetch the home page and up to four of the app's own script files.
- Do not log in.
- Do not make database or API calls.
- Respect robots.txt.
- Do not run JavaScript.
- Report aggregate findings only.
The dataset and methodology, available under CC BY 4.0, provide the basis for the figures and comparisons in this article.
This approach can identify observable configuration gaps and content present in fetched files. It cannot establish whether RLS or other authorization controls are correct. Code and behavior outside the fetched material remain outside its scope. It also cannot turn an absence of detected leaks into proof that no leaks exist elsewhere.
What to do next
- Run the AI-built app security check on a page you own. It is free with no sign-up, checks one page per run, and uses a passive security audit.
- Prioritize any exposed secret credentials, then verify backend authorization in your own project.
- Review headers, cookies, DNS records, and suitable third-party script integrity settings.
- After deploying fixes, check the page again and repeat your owner-side permission tests.
Frequently asked questions
Does a good security score guarantee an app is safe?
No. A passive score reflects observable checks, not a complete review of an app’s code, authorization or runtime behavior.
Should I remove a Supabase public key from my frontend?
A public anon or publishable key is intended for client use. Focus on reviewing and testing RLS policies, and never place a service-role key in client code.
Does removing a leaked key from the code make it safe again?
No. Revoke or rotate the exposed key with its provider, then review relevant usage records and replace it with a server-side credential.
Want to see how your own site does? Run a free audit at sitecheckly.com.
Figures in this article come from Sitecheckly's own audit data; see the methodology.
Top comments (0)