Security Hardening Checklist
Production-readiness posture for security — what to verify before shipping.
This page is a checklist, not a tutorial. It tells you what to verify before an application ships, not how to wire each piece. For the how-to — middleware order, configuration examples, JWT auth — see the Security guide.
Each item below links to the guide section or reference page that shows the implementation. Work through the checklist before a production release; re-run it after any change to middleware order, CORS origins, or secret handling.
Security headers
-
@nextrush/helmetis registered, and registered early in the middleware chain (before routing). -
contentSecurityPolicyis not disabled. The default ({ useDefaults: true }) is starting-point only — a real deployment defines its owndirectivesfor the scripts, styles, and origins it actually serves. - HSTS (
hsts) is enabled withincludeSubDomainsfor any domain served entirely over HTTPS.preloadis opt-in and cannot be safely reversed quickly — verify the domain is HTTPS-only everywhere before enabling it. - Cross-origin isolation headers (
crossOriginEmbedderPolicy,crossOriginOpenerPolicy,crossOriginResourcePolicy) match what the app actually needs to embed or be embedded by — the defaults are restrictive (require-corp/same-origin/same-origin) and can break legitimate cross-origin asset loading if left unexamined.
Reference: @nextrush/helmet ·
How-to: Security guide — Security Headers
CORS
-
originis an explicit list of allowed origins, or a validation function — never a wildcard ('*') in production.@nextrush/corswill not combine wildcard origin withcredentials: true; perglobal-rules.instructions.mdthis combination is never acceptable even outside that guard. -
credentials: trueis set only for routes that actually use cookies orAuthorizationheaders cross-origin — enabling it broadly widens the attack surface for no benefit. -
methodsandallowedHeadersare scoped to what the API actually accepts, not left at defaults that allow every method. - Preflight
maxAgeis set to reduce OPTIONS request volume, but is not so long that a CORS policy change takes days to propagate to cached browsers.
Reference: @nextrush/cors ·
How-to: Security guide — CORS
CSRF protection
- If any route authenticates with cookies,
@nextrush/csrfis registered and itssecretis at least 32 characters, sourced from an environment variable. - Bearer-token-only APIs (no cookie-based session) have confirmed CSRF does not
apply — a browser cannot attach an
Authorizationheader on a cross-site request, so token-only auth is not vulnerable to CSRF by construction. Do not add CSRF middleware to a route that has no cookie-based auth; it adds cost with no security benefit there. - The CSRF secret is rotated on the same schedule as other application secrets, not left as a one-time setup value.
Reference: @nextrush/csrf ·
How-to: Security guide — CSRF Protection
Rate limiting
- Every publicly reachable endpoint has a rate limit —
@nextrush/rate-limitapplied globally at minimum. - Authentication endpoints (login, register, password reset) have a stricter, route-level limit than the global default — credential-guessing endpoints are the highest-value target for abuse.
- If the app runs behind a reverse proxy or load balancer,
trustProxyis explicitly configured. Without it, every request appears to originate from the proxy's IP and the rate limiter throttles all users together instead of per-client. - The rate-limit store matches the deployment topology: the default in-memory store is per-process state — see Scaling for why that matters once you run more than one instance.
Reference: @nextrush/rate-limit ·
How-to: Security guide — Rate Limiting
Secrets management
- No secret, API key, or credential is hardcoded in source — this is a
zero-tolerance rule, not a style preference (see
global-rules.instructions.md§2). - All secrets (CSRF secret, JWT signing key, database credentials, third-party API keys) are read from environment variables at startup, and startup fails loudly if a required secret is missing — not silently falling back to an insecure default.
-
.envfiles are excluded from version control and from any error response or log line. - Secrets are rotated on a defined schedule, and immediately on any suspected compromise.
For how environment variables are loaded and validated at startup, see Configuration.
Error handling
- The global error handler never serializes
error.stack,error.cause, file paths, or raw query/database errors into a client-facing response. - 5xx responses return a generic message; 4xx client errors may surface
error.messagesince that content is meant for the caller. - Errors are still logged in full detail server-side — hiding detail from the client is not the same as losing observability. See Observability for structured error logging.
How-to: Security guide — Error Handling Security
Dependency auditing
-
pnpm audit(or the equivalent for your package manager) runs in CI, not only locally before a release. - Dependencies are pinned to exact or narrowly-ranged versions — open ranges
(
^,*,latest) are avoided so an audit result is reproducible. - New dependencies are vetted for maintenance status and typosquatting risk before being added, per the project's own dependency-management standard.
Request size limits
-
@nextrush/body-parser'slimitoption is set explicitly — an unbounded body size is a denial-of-service vector. - File-upload routes using
@nextrush/form-dataset a limit appropriate to the upload type, rather than reusing the global JSON body limit.
Health endpoints
-
/readyz(from@nextrush/health) is not exposed through a public-facing load balancer or gateway if its check-name breakdown (which dependencies exist and their pass/fail state) should not be visible outside your cluster. -
livezPath/readyzPathare exempted from@nextrush/rate-limit(or mounted before it), so a legitimate high-frequency orchestrator probe is never throttled as abusive traffic.
Reference: @nextrush/health
Response-timing headers
-
@nextrush/timer'sX-Response-Time/Server-Timingheaders are disabled or stripped on routes where response latency itself is sensitive (e.g. authentication endpoints) — precise timing can let an attacker distinguish code paths (a valid vs. invalid username, a cache hit vs. miss) by latency alone, independent of the response body or status code.
Reference: @nextrush/timer