Free check
Is your AI-built app leaking? Find out in 10 seconds.
A free website security check for AI-built and vibe-coded apps. Passive checks only. Nothing is stored.
Informational only. Passive public checks, not a security audit, no guarantees. ShipSafeStack.
Only scan sites you own or have permission to check. Nothing you submit is stored.
Loading the check…
What the free check looks at
This is a free website security check for AI-built and vibe-coded apps, and for any other public URL. It sends ordinary GETs, the way a browser would load the page. It does not log in, post a form, or change anything on the site. Informational only. Passive public checks, not a security audit, no guarantees. ShipSafeStack.
HTTPS
The check loads the URL you typed, then requests the same host over plain HTTP. It records whether the page stayed on HTTPS and whether HTTP redirected there.
A page that stays on HTTP, or an HTTP URL that never redirects, sends the app in the clear. AI builders often ship the preview on HTTPS and leave the HTTP address open.
Pre-launch checklistStrict-Transport-Security
It reads the Strict-Transport-Security header on the HTTPS response and looks for a max-age greater than zero.
HSTS tells the browser to keep using HTTPS on later visits. Without it, a later visit can still start on HTTP.
Pre-launch checklistContent-Security-Policy
It checks that a Content-Security-Policy header is present. It does not grade how strict the policy is.
A policy is one of the controls that limits which scripts and frames a page will load. A missing header is a gap. A present header is not proof the policy is tight.
Pre-launch checklistFraming
It looks for X-Frame-Options set to DENY or SAMEORIGIN, or a Content-Security-Policy frame-ancestors directive.
Without one of those, another site can put your page in a frame. That is the setup clickjacking uses.
Pre-launch checklistX-Content-Type-Options
It looks for the nosniff value on X-Content-Type-Options.
nosniff tells the browser not to guess a content type. A stylesheet or script served with the wrong type is less likely to be executed as something else.
Pre-launch checklistReferrer-Policy
It checks that a Referrer-Policy header is present. It does not require a particular policy.
The referrer can carry the full URL, including query tokens, to the next site. A policy is how you limit that.
Pre-launch checklistPermissions-Policy
It checks that a Permissions-Policy header, or the older Feature-Policy header, is present.
The header is where a page turns off camera, microphone, and other powerful features it does not use.
Pre-launch checklistExposed files
It requests a short list of common paths: /.env, /.env.local, /.git/config, /.git/HEAD, /.DS_Store, /config.json, and /backup.zip. A path counts only when the response is HTTP 200 and the body matches that kind of file. The check never prints the file.
A public .env or git directory is the app's secrets and history, not a missing header. Builders sometimes deploy the project folder as the site root.
API keys in the frontendKeys in public scripts
It reads the homepage HTML and up to about ten same-origin scripts that page loads. It looks for secret-shaped strings, including a Stripe secret key, a Supabase service-role JWT, and a private key block. A hit is shown as the first four characters and a mask, never the full value.
Anything in the script the browser downloads can be copied. A key next to a fetch is a common shortcut in generated code.
API keys in the frontendSupabase anon key
If a JWT in those public scripts has the role anon, the check reports it as information. It does not treat that key as a failure by itself.
Supabase documents the anon key as a client key when row level security is on. The check cannot see whether those policies exist.
Is the Supabase anon key safe to expose?Source maps
It looks for a sourceMappingURL in the scripts it fetched, and requests a same-origin .map file. An embedded map, or a map that returns source-map JSON, is a warning.
A public source map can include the original source, comments, and env names that were never meant for the browser.
Pre-launch checklistRate limiting
This pass does not send a burst of requests. The row stays at couldn't check.
A public form or API with no limit is an abuse problem. The check cannot measure it without becoming that abuse.
Rate limitingStripe webhook verification
This pass does not send a webhook. The row stays at couldn't check.
A handler that trusts the JSON body without the Stripe signature can be called by anyone who can reach the URL.
Stripe webhooks
What the check cannot see
A pass on the rows above is not a clean bill of health. These are the gaps that matter on an app a builder generated.
Row level security and database grants
The check never signs in and never queries a database. It cannot tell whether a second user can read the first user's rows, or whether a table is open to the anon role.
Server-side logic and secrets that never reach the browser
A key that lives only in a server environment, an Edge Function, or a private repository is invisible here. So is a service-role key that was copied into a chat and never into the built JavaScript.
Supabase service role key exposedLeaked a GitHub token?API keys in the frontend
Auth, payments, and abuse controls
The check does not create an account, pay, or forge a webhook. It cannot tell whether a session is checked on the server, whether a price is decided in the browser, or whether a route limits retries.
Example result
Example only. These rows were written by hand so you can see the layout. They are not a scan of example.com, and they are not a result for any product. Nothing here was stored.
Illustration URL: https://example.com
Informational only. Passive public checks, not a security audit, no guarantees. ShipSafeStack.
- Pass
- Warn
- Warn
- Pass
- Fail
Keys in public scripts
Sample: a made-up key shape, sk_l****, in a script the illustration page loads. This is not a real key.
How to fix - Info
- Couldn't check
FAQ
- Is the free website security check an audit?
- No. It is a passive look at a public URL: the page, a few response headers, a short list of common files, and scripts the homepage loads. It is not a penetration test, a certification, or a guarantee. A quiet result means these particular checks did not flag a row. It does not mean the app is free of problems.
- What does the check look at on an AI-built or vibe-coded app?
- The same things it looks at on any public URL. Generated apps often ship a key in the client bundle, a missing security header, or a project file such as .env at the site root. The check looks for those on the public page. It does not log into the builder, and it does not read the builder's dashboard.
- What can the check not see?
- It cannot see row level security, database grants, server-side code, or secrets that never appear in the public page. It does not send a Stripe webhook or a burst of requests, so those two rows stay at couldn't check. A private GitHub token that was pasted into a chat is also outside this check.
- Do you store the URL or the result?
- No. The check runs when you submit the form, returns the rows, and does not keep the URL or the result. A link you copy is only the URL you typed, placed on /scan so the same check can run again in the browser.
- Can I check a site I do not own?
- Only scan sites you own or have permission to check. The requests are ordinary public GETs, and they are still requests against someone else's server.