Cybersecurity
What a Website Should Check Before It Goes Live
A practical pre-launch checklist for modern websites — trust signals, security basics, redirects, forms, and the avoidable mistakes that still reach production.
Launching a website is not the same as finishing it. Before anything goes live, the basics need to hold: forms, redirects, trust signals, hidden settings, and the parts most teams assume are “probably fine” because the build succeeded.
This is the kind of review we run on CATALYST builds before launch. It is not meant to sound dramatic. It is meant to catch the quiet failures that damage trust later: exposed settings, weak guards around forms and routes, and avoidable technical debt at the edge.
1. Know what is public
Anything prefixed with NEXT_PUBLIC_ is readable in the browser. That is by design. Before launch, search the repo for public env vars and ask a blunt question: would we be comfortable printing this value in the page source?
- API keys, webhook secrets, and private service tokens must never use NEXT_PUBLIC_.
- Server-only modules should never be imported into client components by accident.
- Confirm .env* files are gitignored and that preview deployments do not inherit production secrets casually.
// Server-only — never import into a Client Component
import "server-only";
export function getStripeSecret() {
const key = process.env.STRIPE_SECRET_KEY;
if (!key) throw new Error("Missing STRIPE_SECRET_KEY");
return key;
}2. Lock down headers early
Security headers are cheap insurance. In App Router projects, set them in next.config or middleware and verify them on the live host — CDNs and platform defaults can strip or override what you think you shipped.
| Header | Why it matters | Baseline |
|---|---|---|
| Content-Security-Policy | Reduces XSS blast radius | Start strict; allowlist only what you need |
| Strict-Transport-Security | Forces HTTPS after first visit | max-age with includeSubDomains |
| X-Frame-Options / frame-ancestors | Stops casual clickjacking | DENY or SAMEORIGIN |
| Referrer-Policy | Limits URL leakage | strict-origin-when-cross-origin |
| Permissions-Policy | Turns off unused browser APIs | Disable camera, mic, geo by default |
3. Treat Route Handlers like APIs
App Router route handlers are public endpoints the moment they are deployed. Auth, rate limits, input validation, and method allowlists belong there — not “we will add that later.”
- Validate every body and query with a schema (Zod or equivalent).
- Reject unexpected content types and oversized payloads.
- Authenticate before side effects — email sends, CRM writes, file uploads.
- Return generic errors to clients; log specifics server-side.
4. Auth boundaries and redirects
Open redirects still appear in polished products: a next= parameter that accepts an absolute external URL is enough for phishing. Allow only relative paths, or an explicit allowlist of hosts.
If a stranger can craft a URL that ends on your domain and then jumps to theirs, you have built the first half of a scam.
CATALYST security review notes
5. Dependencies and the edge
Run npm audit before release, but do not stop there. Check which packages execute at build time versus request time. Prefer well-maintained libraries for crypto, auth, and HTML sanitization — and keep Next.js itself current enough that known platform CVEs are not sitting in production for months.
Pre-production gate
- No secrets in client bundles or public env.
- Headers verified on the production hostname.
- Every mutating route authenticated, validated, and rate-aware.
- Redirects cannot leave your origin unexpectedly.
- Dependency and Next.js patch level documented for the release.
Pass that gate, then schedule a real review. Checklists prevent own-goals. They do not replace adversarial testing when the product holds accounts, payments, or sensitive data.
Related
