Vibe Coding Security Checklist to Run Before Launch
Key takeaways
- A vibe-coded app can ship with an API key in frontend code. If that key is in the page the browser downloads, it is public. Anyone who opens the site can read it and spend on the owner's provider account.
- You do not need a security title. You need this list on your own project before launch.
- In Claude Code, type
/security-review. It reviews the diff between your branch andorigin's default branch for injection, authentication issues, and data exposure. It needs a git repo with anoriginremote. It reports findings. It does not apply them. - Read the report, ask Claude for a fix you accept, review the edit, and run the command again. The ten checks still stand.
What this vibe coding security checklist is for
Vibe coding means you describe the app and an AI writes most of the code. A working screen can show up in an afternoon. So can a paid API key pasted into a file the bundler sends to every visitor.
A key in the frontend is a doormat with the house key under it. The page is built to load for strangers. If the secret is in that page, it is not a secret.
This is the page behind the reel. Comment CHECK and you land here. Walk the ten checks, then run /security-review on the branch you will deploy. The command ships with Claude Code. It is not a CodeBaseHub feature.
Where a key shows up once the site is built
A provider key stays private only when the browser never receives it. Server code reads it from an environment variable and calls the provider. The browser calls your server.
The leak is the reverse. The key sits in a client component, in config the bundler includes, or in a public env prefix: NEXT_PUBLIC_, VITE_, or EXPO_PUBLIC_. Those prefixes inline the value into the client bundle. A site URL belongs there. A secret that can spend money does not.
Build for production, search the output you will serve, and open your own deployed page. View source and the JavaScript the browser downloads. If the key is in that response, it is public. Search your build, not someone else's site.
Deleting the line in the latest commit does nothing for an older commit, a screenshot, or a chat paste. The old key works until the provider revokes it.
Ten checks before you launch
1. Keys only in server environment variables
Search client components, shared frontend config, and mobile screens for long tokens and for a provider name next to a quoted secret. Good: the secret is read only on the server, from an env var with no public prefix, and the browser calls your route instead of the provider.
2. No secrets in the client bundle
Build the way you ship. Search the output (dist, .next, build, or the exported web bundle) for the real key. Search source for NEXT_PUBLIC_, VITE_, and EXPO_PUBLIC_ values that are not meant to be public. Good: zero hits for the secret. Public env vars hold only values that are already fine to show, such as a site URL or a publishable client key with no spend rights.
3. .env is not committed
From the repo root, list tracked env files with git ls-files filtered to .env. Check history for a commit that added one, even if a later commit deleted it. Good: no tracked .env, .env.local, or .env.production. A .env.example with blank values is fine. Real values stay on the machine or in the host's secret store.
4. .gitignore covers secret files
.gitignore should list .env and .env.*, with an exception only if you track .env.example, plus credential files you use (*.pem, service-account JSON). Create a dummy .env.local and look at git status. Good: git does not offer that file for commit. An ignore rule added after a file was tracked does nothing until you untrack the file.
5. Rotate a key that was ever in git, a screenshot, or a chat
If item 3 or 4 fails, or the key was on a slide, in a screen recording, or in a ticket, treat it as public. Create a new key, store it only in server env, deploy, then revoke the old key. Deleting the file from the latest tree does not revoke it. GitHub secret scanning flags known credential patterns in repository content, and on public repositories that scan runs automatically. It is a backstop. Rotation is the fix. Good: the provider rejects the old key, and the new key is absent from git and from the client bundle.
6. A spend cap or billing alert is on before the first user
Open the provider account that key bills. Turn on the spend cap or billing alert the account offers, and send it to an inbox you actually read. Good: a limit that stops or throttles calls, not only a receipt after the fact. A cap does not repair a leaked key. It shortens the window if a check above was wrong.
7. Write endpoints check the caller
List handlers that create, update, or delete data: POST, PUT, PATCH, DELETE, and server actions. Find the line that loads the session or token and rejects the request when it is missing. Good: an unauthenticated call stops before any write, and the user id comes from the session, not from a field the client can set. Hiding a button is not authentication.
8. No service-role or admin key in the browser
Search client source and the built bundle for service-role keys, secret keys, and admin tokens that skip row-level rules or act as the project owner. A publishable or anon key that is designed to be public, and that those rules constrain, may stay in the client. The key that skips the rules may not. Good: admin work only on the server, that key only in server env, and a client search with no hits.
9. The lockfile is committed, and you have read the audit
package-lock.json, pnpm-lock.yaml, yarn.lock, or the equivalent should be in git so installs repeat. Run the package manager's audit. Read high-severity advisories in packages that handle auth, payments, or HTML. Good: the lockfile is in the repo, and you are not ignoring a critical issue on those paths. Do not upgrade every dependency on launch day. Fix, or explicitly accept, the ones that touch those paths.
10. /security-review has been run, read, and run again
Open Claude Code in this repo and type /security-review at the start of the message. Good: a report you have read, fixes you accepted and re-checked, and items 1–9 still true. A clean report on an empty diff is not a sign-off. The next section says why.
How to run /security-review
/security-review is a built-in Claude Code command in the commands reference. It is not /code-review.
Type it at the start of a message, in a session opened in the project directory. It diffs your current branch against origin's default branch and looks for injection, authentication issues, and data exposure. It needs that origin remote. The commands page notes an ambiguous argument error if the base is unclear, and points to an error reference. Fix the remote, then run it again.
It reads source in your checkout. It does not open the live site. A passing run does not prove a deployed bundle is clean.
The help center calls this an on-demand check before you commit. After findings, you can ask Claude to implement fixes. The same page says automated reviews complement manual review. They do not replace it.
There is no documented --fix flag on /security-review. --fix belongs to /code-review. Do not invent a flag. Ask in a sentence, then read the diff before you keep it.
What to do with the result:
- Read each finding. If you reject one, write down why.
- Ask Claude in that session to implement a fix you accept. Review the edit.
- Run
/security-reviewagain. - If your branch matches
origin's default branch, the diff can be empty. Empty does not mean the whole repo was scanned. Security guidance says/security-reviewcovers the current branch's changes and reads the checkout, not a running service. For a file already on the default branch, ask Claude to review that file, and still walk the ten checks.
A separate security-guidance plugin can review code while Claude writes and address findings in the same session. That is a different install. Typing /security-review does not turn it on. Screenshots, old commits, and a key already in a deployed bundle are items 2, 3, and 5, not this command.
FAQ
Do you need to be a security expert?
No. These mistakes show up in your own repo: a secret in client code, a tracked .env, a write route with no session check, an admin key in the bundle. Search and git cover those. /security-review adds one read of the branch diff. Neither makes you a penetration tester, and neither certifies the app.
What if the key was already in the repo?
Rotate it. Issue a new key, store it only on the server, deploy, and revoke the old key. Deleting the line leaves the old commit in history. A screenshot or a chat paste is the same case. Afterward, confirm the new key is not tracked and not in the client bundle.
Does /security-review replace the checklist?
No. It is one pass over the current branch diff, and it needs origin. It will not notice a spend cap you never set, a screenshot, or a key that reached the default branch long ago if that change is no longer in the diff. Use the list for those. Use the command on a fresh change, then read the output. An unread report has not reviewed anything.
Before you deploy
Walk items 1–9 on the branch you will ship. Run /security-review, keep only fixes you have read, and run it again. If a key was in the client, in git, or in a screenshot, rotate it before deploy.
Related articles
- 20 Claude Code Slash Commands Most Developers Never Use/goal, /fork, /rewind, /loop, /doctor plus 15 more underused Claude Code slash commands—with copy-paste examples for sessions, parallel work, and shipping.
- 3 Claude Code Mods That Change How the Agent BehavesAnthropic's three sample Claude Code mods—Token Weather, Blast Radius, Replay Theater—change context UI, risky shell, and edit review. Needs v2.1.287+.
- ElevenLabs MCP Claude Code: Hosted Install, OAuth, and Creative ToolsInstall the hosted ElevenLabs MCP in Claude Code with one HTTP command, complete OAuth via /mcp, then generate speech, music, images, and video—or manage voice agents—without a local server or API key.