Skip to content
ShipSecurelySecurity reference
Menu
Your tool here — sponsor ShipSecurely

Printable

Pre-launch security checklist

A single pass over the issues that most often ship in an AI-built app, before you send the URL to anyone else.

Last updated

Print this page and tick the boxes, or paste the prompt at the bottom into the coding agent that built the app. Each line links to a longer guide. This is a practical list, not a penetration test and not legal advice. Do the checks on a project you own.

Markdown version

Data access

Secrets

Money and abuse

Injection and the browser

  • User input is not concatenated into SQL or into a Supabase .or() filter string.

    SQL injection

  • User and model text is rendered as text, or sanitized with a maintained allowlist. No homemade HTML filter.

    Cross-site scripting (XSS)

  • Tools the model can call check the session on the server. The model does not decide who the user is.

    Prompt injection in LLM features

  • Uploads have a server-side size and type limit, a generated filename, and are not served as HTML or SVG from your origin.

    Unsafe file uploads

  • Cookie-authenticated APIs do not reflect arbitrary Origin headers. There is an allowlist, or no CORS middleware at all.

    CORS wide open

  • Responses send nosniff, a referrer policy, and frame protection. HSTS is only set if the site is HTTPS-only.

    Missing security headers

Accounts and launch

  • Password reset uses the auth provider's email flow, or a long single-use token. It does not update a password from an email alone.

    Weak password reset

  • The lockfile is committed, and you have read the current dependency audit instead of force-upgrading.

    Outdated dependencies

  • Privacy and terms pages exist, name the processors you actually use, and point at a contact address that reaches you.

    Missing privacy policy and terms

Give the whole list to your agent

You are doing a pre-launch security pass on this repository. Do not add features. Do not claim the app is secure. Work through the list below and change code only where you can see the problem. If you are unsure, write a question instead of weakening a control.

Check and fix what you can:
1. Supabase: enable RLS on public tables and replace policies of using (true). Do not use the secret key in client code or NEXT_PUBLIC_ variables.
2. Firebase: remove allow read, write if true. Scope rules to request.auth.uid and the owner field.
3. Storage: private buckets, owner-only prefixes, no user HTML or SVG served from this origin.
4. Every Route Handler and Server Action that reads or writes data must load the session and scope queries to that user. Ignore userId, role, price, and plan from the client.
5. Stripe webhooks must verify the signature on the raw body. Prices must come from server-side price ids. Only the verified webhook grants a plan.
6. Model routes must keep the provider key on the server, require a user, and enforce a small per-user daily cap. Tell me to set a spend limit in the provider dashboard.
7. Add server-side rate limits on login, password reset, and paid routes.
8. Parameterize SQL. Render user and model text as text. Allowlist CORS origins. Add nosniff, referrer policy, and frame-ancestors none.
9. Password reset must not set a password from an email alone.
10. Do not print secrets. Tell me which keys I must rotate if they were committed or shipped to the browser.

End with a checklist of what you changed, what you could not verify from the repo, and what I should click-test.