The Pre-Launch Security Checklist: Ten Checks Before You Ship

Written by the Rafter Team

Most side projects that get hurt after launch are not hit by a clever attack. They leak a key from a public repo, leave an API route open, or let anyone read a database table. Each of those takes one command or one click to find, so find them before you ship.
Replace yourapp.com with your domain in the commands below.
Most checks take a minute or two; the backup check takes longer.
The checklist
-
No secrets in the code. A secret is any value that lets its holder act as your app, such as an API key or database password. Run
rafter secrets .from the repo root (free, no account; install below). It exits with status 1 and names the file and line if it finds one. To also check commits you have since deleted the key from, runrafter agent init --with-betterleaksonce, thenrafter secrets --history. If anything turns up, revoke the key at the provider before you do anything else. -
No
.envfile in git. Rungit ls-files | grep -E '(^|/)\.env'. The only line you want back is a.env.examplewith no real values. If a real.envis tracked, Secrets, API Keys, and .env Files, Done Right covers how to untrack it and why its keys need replacing. -
HTTPS, with a redirect from HTTP. Run
curl -sI http://yourapp.com | grep -iE '^(HTTP|location)'and expect a301or308with alocationthat starts withhttps://. Then runcurl -sI https://yourapp.com | grep -i strict-transport-security. A line back tells browsers to use HTTPS for your site on every later visit. For the other headers to set, see the security headers check. -
Auth on every API route, tested logged out. Pick a route that should need a login and call it with no cookie or token:
curl -s -o /dev/null -w '%{http_code}\n' https://yourapp.com/api/your-route. Expect401or403. A200means anyone on the internet can call it. Five mistakes AI-written apps ship with shows how to copy a real request from your browser and also test one user reading another's data. -
Database access rules on every table. On Supabase, run this in the SQL editor:
select tablename, rowsecurity from pg_tables where schemaname = 'public';Every table holding user data should showtrue.falsemeans row-level security, the rule that limits each user to their own rows, is off, and anyone with your public key can read the table. Supabase's built-in Advisors flag the same problem asrls_disabled_in_public. -
Dependencies with known holes. Run
npm audit, orpip install pip-auditand thenpip-audit. Fix anything rated high or critical in a package your app ships. Lower ratings can wait a week. -
A spend limit on every paid API. Real rate limiting takes longer than one night to build. Tonight, set a monthly spend limit in your AI provider's console (OpenAI and Anthropic both offer one) and a billing alert on your cloud account. That puts a ceiling on what a leaked key or a runaway loop can cost you.
-
Error pages that hide the internals. Send the deployed app something it should reject, like a malformed form field or a bad ID in the URL, and read the response. A file path, a line number, or a stack trace means the app is running with debug output on in production.
-
A backup you have restored. This one takes longer than a minute. Restore your latest backup into a scratch database and confirm your data comes back. Until you have done that once, you do not know what your backup holds.
-
Debug and admin routes removed. Try the paths a framework or AI tool might have left behind, such as
/api/debug,/admin, or/_debug:curl -s -o /dev/null -w '%{http_code}\n' https://yourapp.com/admin. Expect404, or a redirect to a login page you meant to have. Then search your code for debug switches left on:grep -rnE --exclude-dir=node_modules 'DEBUG ?= ?True|debug: ?true' .
Use Rafter to keep item one true
Nine of these checks hold until you change the thing they check. Item one breaks the next time anyone commits a key, so automate it. Rafter's CLI is open source and free, and its secret scan runs on your machine with no account and no API key:
npm install -g @rafter-security/cli # or: pip install rafter-cli
rafter secrets . # tonight's check
rafter agent install-hook # every commit after tonight
The hook scans staged changes and blocks a commit that contains a secret, so a key in next month's pull request stops at your laptop instead of turning up in a history scan a year from now.
If an agent writes some of your code, rafter agent init --with-claude-code or --with-codex also gives Claude Code or Codex hooks that stop risky shell commands before they run.
Run the ten checks tonight, install the hook before you close the terminal, and ship.