Triage by what a stranger can see
You have one hour before the launch post goes out, and you cannot review the whole app. The useful move is not a longer checklist. It is an order of operations.
The right order is detectability from the outside. A stranger with your public URL, a browser, and no account sees some failures instantly and others only after probing. Check the instantly visible ones first, because those are the ones a crawler, a curious reader, or an opportunist finds within minutes of your link spreading. If you only have time for the first two gates, that is still a better hour than reading config files you wrote yourself.
This note is a pre-launch security checklist for AI app builders, focused on the go/no-go decision in that final window. It does not replace the broader pre-ship review. For the full pass, see the AI-built app launch security checklist and the solo-founder pre-launch checklist linked below. This page is the triage layer that sits on top of them.
Run each gate against the deployed production URL, not local development. Middleware, a CDN, and platform rules change what the browser actually receives. Use a clean browser session or a private window so an existing login does not mask a missing auth check.
The five go/no-go gates, in order
Work top to bottom. Each gate has a quick check you can do in the last hour and a binary condition that holds the launch. The order is deliberate: gates one through three are visible in the browser with no probing, gate four needs a guessed URL, and gate five needs you to know one real data route.
- A secret or API key in the client bundle. Open DevTools, go to the Network tab, reload the page, and search the loaded JavaScript and JSON responses for sk_, key, secret, token, AKIA, and your provider's prefixes. A publishable or anon key is expected and fine; a secret key, service-role key, or private API token is not. Hold the launch if a secret-shaped string that grants write or admin access ships to the browser. This is the most visible failure and the hardest to walk back once the URL spreads, so it goes first.
- A public source map exposing internal routes. In the Network tab, look for .js.map files loading in production, or a //# sourceMappingURL= comment at the end of your bundle. Open one and scan for admin route names, internal API paths, and feature flags. A source map is not automatically a breach. Hold the launch if the map reveals admin routes, private API paths, or secret-handling code that makes the next probe obvious. Otherwise treat removing it as a hardening task, not a blocker.
- Missing security headers. In the Network tab, click the document request and read the Response Headers. Check for Content-Security-Policy, X-Content-Type-Options: nosniff, a framing control (X-Frame-Options or CSP frame-ancestors), and Referrer-Policy. Hold the launch only if framing is unrestricted on a page that handles login or payments, where clickjacking is a realistic path. Missing headers elsewhere are a same-day hardening task, not usually a go/no-go blocker on their own.
- A publicly readable storage bucket. If your app serves uploads, avatars, or exports, copy one asset URL from the Network tab and open it in a private window with no session. Then try to list the bucket or guess a neighboring object path. Hold the launch if an unauthenticated request returns another user's file, or if the bucket lists its contents to anyone. This is authorization, not authentication: the request is anonymous and still gets data it should not.
- A route that loads real data without auth. List the routes that show user or business data: a dashboard, a record detail page, an export endpoint, an internal API path. Open each in a private window with no login. Hold the launch if any of them returns real data, or an API route returns a real JSON payload, to an unauthenticated request. This is last because it needs you to know a real data route, but it is often the highest-impact failure, so do not skip it if time runs short on the earlier gates.
Gates one, four, and five are authorization and exposure failures: the request needs no valid account and still gets something it should not. Treat those as hard launch blockers. Gates two and three are usually hardening tasks unless they sit directly on a login or payment surface.
Why AI-built apps land here
These five failures cluster in AI-built apps for a few specific reasons, not because generated code is insecure by nature.
The fast-deploy path skips the review loop where a human would normally catch a secret in client code or a public map. The app works in the demo, the URL goes live, and nobody checked the Network tab from a logged-out session. Secrets reach the bundle when a key meant for a server route gets imported into a component, or pasted into a public environment variable, because the generated example did not separate the two clearly.
Source maps ship because production builds default to emitting them, and the deploy step never turned them off. Headers are missing because framework and host defaults are tuned for local development, not a public boundary. Buckets stay open because the storage rule that says "anyone can read" is the path of least resistance during the build, and it never got tightened. And the unauthenticated data route is the one the builder always visited while logged in, so the missing check never showed up in manual testing.
What to fix in the last hour, and what to defer
You will not fix everything in an hour, and you should not try. Sort what you find into two buckets.
Fix before you post: a write-capable or admin secret in the bundle (rotate the key, move it server-side), an unauthenticated route or API that returns real data, and a bucket that serves another account's files. These are exposure and authorization failures with no account required, and they get worse the moment the link spreads.
Defer to a same-day hardening pass: a public source map that does not reveal admin internals, and missing headers on pages that do not handle login or payments. Add the headers, disable source maps in the production build, and rerun the check. None of those needs to block the launch unless it sits on a sensitive surface.
One honest limit: passing all five gates means the obvious public-surface failures are not present. It does not mean the authorization logic behind your data routes is correct. A route can require a login and still return data the logged-in user should not see. That is a tenant-isolation and authorization question, and it needs a manual look at the code, not a one-hour external check.
Where VibeCodeGuard fits, and what it cannot prove
VibeCodeGuard's Launch Check is built for exactly this window. It runs once against your public URL and surfaces missing security headers, public source maps, exposed build and deploy artifacts, secret-shaped strings in the client bundle, and publicly readable buckets and endpoints. It returns severity and fix guidance so you can triage findings the way this note describes, before you post the link. It compresses the first part of these gates into a single external pass instead of five manual ones.
It is a public-surface signal, not proof the app is secure. The scan cannot confirm that a route requiring authentication enforces the right authorization, cannot test business logic, and is not a penetration test or a code review. A clean Launch Check means the visible launch-day failures are not present; it does not certify the app. Auth-logic correctness, tenant isolation, and access-control decisions still need a manual look at the code.
Run a focused Launch Check against the public URL before you share it, triage the findings by severity, fix the exposure and authorization blockers, and rerun from a clean browser session. Then post the link.
A clean external scan tells you what a stranger can see. It does not tell you whether your authorization checks are correct. Confirm that part in the code before launch.
> launch check
Scan the public surface before launch.
Get severity, evidence, and practical fix guidance for the checks VibeCodeGuard can run from the outside.
> sources