Next.js + Supabase production launch checklist
Next.js + Supabase is the most common stack we scan, and the same handful of issues come up repeatedly. This checklist focuses on those repeat offenders and the framework-specific fixes (App Router middleware, server actions, env var conventions).
14 checks
Tick through each one
Click any item to open the detailed fix guide. The detector tag shows which scanner module flips the state pass or fail when you run a SafeToShip scan.
RLS enabled on every public schema table
CriticalDetector: supabase
Service role only in server handlers (no client import)
CriticalDetector: js-secrets
Only safe values use NEXT_PUBLIC_ prefix
CriticalDetector: js-secrets
.env not deployed
CriticalDetector: exposed-files
Middleware runs auth check before protected routes
HighDetector: tech-detect
CSP via middleware with per-request nonce, no unsafe-inline
HighDetector: headers
HSTS via next.config.js headers
HighDetector: headers
frame-ancestors directive set in CSP
HighDetector: headers
API route CORS allowlist (or no CORS at all if same-origin)
HighDetector: cors
Auth cookies Secure + HttpOnly + SameSite=Lax
HighDetector: cookies
Rate limiting on /api/* and Server Actions
MediumDetector: rate-limit
poweredByHeader: false in next.config.js
LowDetector: tech-detect
Valid TLS, no mixed content
HighDetector: ssl
SPF + DMARC published if your app sends transactional email
MediumDetector: email
Paste this into Next.js
One prompt that runs the entire checklist as a code review pass.
Audit my Next.js + Supabase app: enable RLS with explicit policies on every public table, move every server-only secret out of NEXT_PUBLIC_, confirm the service_role client is imported only in route handlers / server actions / cron, ensure .env is not deployed, add middleware that runs supabase.auth.getUser() before protected pages, set CSP via middleware with a per-request nonce (drop unsafe-inline), set HSTS in next.config.js headers, replace X-Frame-Options with frame-ancestors in CSP, allowlist CORS origins on /api/* routes (or remove CORS for same-origin only), set Secure+HttpOnly+SameSite=Lax on auth cookies, add @upstash/ratelimit on /api/* and Server Actions, set poweredByHeader: false, ensure TLS validity and no mixed content, and publish SPF + DMARC for the sending domain.FAQ
Frequently asked questions
- Should middleware or page-level checks enforce auth?
- Both. Middleware blocks anonymous traffic from reaching protected routes; the page-level check confirms the user identity matches the resource (defense in depth). Skipping middleware risks slow page loads for unauthorized users; skipping page-level risks IDOR attacks.
- Why drop unsafe-inline from CSP?
- unsafe-inline allows any inline <script> to run, defeating the main XSS protection CSP provides. Per-request nonce + strict-dynamic gives you the same flexibility for legitimate scripts (analytics, tag managers) without the XSS hole.
Per-issue depth
Fix guides for this checklist
Supabase RLS disabled
A Supabase table without RLS is readable (and often writable) by anyone with your anon key. Here is exactly how to turn on RLS and write your first policy.
Read moreExposed Supabase service key
The service role key bypasses all security in Supabase. If it is in your client code, an attacker has full database access. Here is how to find and fix it.
Read moreMissing CSP header
A missing Content-Security-Policy header lets attackers inject scripts into your site. Here is what CSP does, why you need it, and how to add it in Next.js, Vercel, and Supabase apps.
Read moreCORS allows all origins
An Access-Control-Allow-Origin: * policy lets any site call your API. Sometimes that is fine, often it is a mistake. Here is how to decide and fix it.
Read moreRun the scan to confirm each check
60 seconds. Free. No account required.