Cyber Monday · Nov 30Early birds get 50% off self-hosted plans. Join the waitlist to lock in the price.Early birds: 50% off self-hostedJoin the waitlist →
The 17 checks

Every mistake we look for, in plain words. 

Hover any card to see the fix. Switch on Dev mode in the menu to see rule IDs and severity codes.

Fix now
Don't launch until this is fixed. (SEV-1)
Fix soon
Fix this before you grow. (SEV-2)
Nice to fix
Good habit, low risk. (SEV-3)
🔑Fix nowSEV-1

A live secret is sitting in your codesecret-in-code

Anyone who reads your code or your site’s JavaScript can copy it and spend your money.

The fix

Rotate the key, then move it to a server-side environment variable.

secret-in-code
How to fix it →
🔑Fix nowSEV-1

Your .env file is committedenv-file-committed

Your .env file is in the repo, so every password in it is public.

The fix

Remove .env from git, add it to .gitignore, and rotate every value.

env-file-committed
How to fix it →
🔑Fix nowSEV-1

A server secret has a browser-visible namepublic-env-secret

A NEXT_PUBLIC_ or VITE_ name ships the secret to every visitor’s browser.

The fix

Drop the public prefix and move the call to a server route.

public-env-secret
How to fix it →
✨Fix nowSEV-1

Your AI key runs in the browserai-key-in-browser

Strangers copy your key from the browser and use your OpenAI credits for free.

The fix

Call the AI from a server route that holds the key.

ai-key-in-browser
How to fix it →
🗂️Fix nowSEV-1

A database table has no row level securityrls-missing

Anyone with your public key can read every row in this table.

The fix

Turn on row level security and add an owner-only policy.

rls-missing
How to fix it →
🗂️Fix nowSEV-1

A database policy lets anyone writerls-open-write

The lock exists, but it’s set to “allow all”. Anyone can edit or delete.

The fix

Replace true with a real condition, like auth.uid() = user_id.

rls-open-write
How to fix it →
💳Fix nowSEV-1

Your Stripe webhook accepts anythingstripe-webhook-unverified

Someone sends a fake “payment succeeded” and gets paid features free.

The fix

Verify every Stripe event with its signing secret.

stripe-webhook-unverified
How to fix it →
🗂️Fix nowSEV-1

User input may be pasted into a SQL querysql-string-concat

A crafted form entry becomes a database command.

The fix

Use a parameterised query. Never build SQL with template strings.

sql-string-concat
How to fix it →
✨Fix soonSEV-2

Your AI route has no spending brakeai-route-no-rate-limit

One script loops overnight and you wake up to a huge bill.

The fix

Add a per-user rate limit and a monthly spending cap.

ai-route-no-rate-limit
How to fix it →
🔐Fix soonSEV-2

Admin access is decided in the browserrole-in-local-storage

Users flip one browser setting and become admin.

The fix

Store roles in the database and check them on the server.

role-in-local-storage
How to fix it →
🌐Fix soonSEV-2

Raw HTML goes straight onto the pageunsanitized-html

A comment with a hidden script runs in every visitor’s browser.

The fix

Sanitise it with DOMPurify, or render it as plain text.

unsanitized-html
How to fix it →
🌐Nice to fixSEV-3

Any website can call your APIcors-wildcard

Other sites can talk to your app on your users’ behalf.

The fix

Replace the wildcard with your own domain.

cors-wildcard
How to fix it →
🔑Nice to fixSEV-3

A secret may be going to your logssecret-in-logs

Passwords end up in logs that more people can read than your database.

The fix

Log that it happened, never the value.

secret-in-logs
How to fix it →
🧰Nice to fixSEV-3

One crash takes down the whole screenno-error-boundary

One bad record gives your users a blank white page.

The fix

Add an error boundary (error.tsx in Next.js) with a retry.

no-error-boundary
How to fix it →
🧰Nice to fixSEV-3

You will hear about errors from your usersno-error-tracking

Your app breaks for a week before anyone tells you.

The fix

Add an error tracker such as Sentry on the client and the server.

no-error-tracking
How to fix it →
🧰Nice to fixSEV-3

Nothing checks that a change did not break loginno-tests

A Friday fix breaks signup until Monday.

The fix

One test each for sign up, log in and pay, run on every pull request.

no-tests
How to fix it →
🧰Nice to fixSEV-3

Your deploys are not repeatableno-lockfile

A package updates itself on deploy and your live app breaks.

The fix

Commit your lockfile.

no-lockfile
How to fix it →