Next.js + Stripe production launch checklist
A Next.js + Stripe checkout has narrow PCI scope (SAQ-A) but a wide attack surface if keys leak or webhooks lack verification. These twelve checks cover the technical baseline.
12 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.
STRIPE_SECRET_KEY only in server-side env
CriticalDetector: js-secrets
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY only in client
CriticalDetector: js-secrets
Webhook handler uses constructEvent with signing secret
HighDetector: js-secrets
Webhook endpoint not rate-limited (Stripe retries)
MediumMost rate limiters break Stripe webhook delivery. Allowlist Stripe IPs instead.
Detector: rate-limit
Per-integration restricted keys for cron / scripts
MediumDetector: js-secrets
.env not deployed
CriticalDetector: exposed-files
CSP allows js.stripe.com in script-src and frame-src
HighDetector: headers
HSTS configured
HighDetector: headers
Cookies Secure + HttpOnly + SameSite=Lax (PCI norm)
HighDetector: cookies
No mixed content on /checkout
CriticalDetector: ssl
Charge / refund routes use idempotency keys
LowDetector: tech-detect
Valid TLS on the production domain
CriticalDetector: ssl
Paste this into Next.js
One prompt that runs the entire checklist as a code review pass.
Audit my Next.js + Stripe integration: confirm STRIPE_SECRET_KEY is server-only, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY only used client-side, every webhook handler calls stripe.webhooks.constructEvent with STRIPE_WEBHOOK_SECRET, the webhook endpoint is NOT rate-limited (use Stripe IP allowlist instead), per-integration restricted keys are used for cron/scripts, .env is not deployed, CSP allows js.stripe.com in script-src and frame-src and not unsafe-inline, HSTS is set, cookies are Secure+HttpOnly+SameSite=Lax, no mixed content on /checkout, and idempotency keys are used on charge/refund routes.FAQ
Frequently asked questions
- Why allow js.stripe.com in CSP frame-src?
- Stripe Elements and Checkout iframe in widgets from js.stripe.com. Without explicit frame-src permission, browsers block the iframes and Checkout silently fails.
- Should I rate-limit the Stripe webhook endpoint?
- No — Stripe retries failed webhooks for up to 3 days, and rate limits will return 429s that look like failures. Instead, allowlist Stripe IPs (published in their docs) and rate-limit everything else.
Per-issue depth
Fix guides for this checklist
Exposed Stripe secret key
A leaked Stripe secret key means an attacker can charge your customers, refund payments, or drain your account. Rotate immediately.
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 moreCookie missing Secure flag
Cookies without the Secure flag can be sent over HTTP, leaking session tokens to anyone on the same network. Here is how to set it.
Read moreMixed content warnings
Loading HTTP resources from an HTTPS page breaks the security guarantee. Browsers block most of it automatically now — here is how to fix the rest.
Read moreRun the scan to confirm each check
60 seconds. Free. No account required.