Skip to main content
nestrs exposes security controls as explicit opt-in builder calls on NestApplication. Nothing is enabled by default — small services that don’t need a particular control don’t pay for it. This page covers each control in order of how frequently you’ll need it, followed by a checklist you can run through before shipping.

Security headers

Call use_security_headers with a SecurityHeaders value to inject protective HTTP headers on every response. SecurityHeaders::default() sets the most broadly applicable headers:
The defaults set:
  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • Referrer-Policy: strict-origin-when-cross-origin
  • X-XSS-Protection: 0
  • Permissions-Policy: geolocation=(), microphone=(), camera=()
For browser-facing APIs that need Helmet-style hardening, use SecurityHeaders::helmet_like(), which adds Cross-Origin-Opener-Policy, Cross-Origin-Resource-Policy, X-DNS-Prefetch-Control, X-Download-Options, and X-Permitted-Cross-Domain-Policies on top of the defaults:
helmet_like() does not set CSP or HSTS automatically — configure both explicitly for your deployment. nestrs runs behind a reverse proxy in most production topologies; HSTS may already be set at the edge.

CORS

CORS is off until you call enable_cors. Pass a CorsOptions value with an explicit origin allowlist for browser clients:
For local development only, CorsOptions::permissive() allows all origins. nestrs emits a tracing WARN at startup if you use permissive CORS when NESTRS_ENV, APP_ENV, or RUST_ENV is set to production.
You cannot combine allow_credentials(true) with a wildcard * origin — browsers reject it. Always set an explicit list when you need credentialed cross-origin requests.

Rate limiting

use_rate_limit accepts a RateLimitOptions value. The defaults allow 100 requests per 60-second window per client IP:
For shared rate limits across multiple instances, enable the cache-redis feature and call .redis(url, key_prefix):

CSRF protection

CSRF protection targets cookie-based browser flows. Bearer token APIs in Authorization headers are not CSRF-bound and do not need this.
1

Enable the csrf feature

2

Enable cookies and CSRF middleware

CsrfProtectionConfig uses a double-submit pattern: your app sets a cookie on safe requests, and the client must echo the same value in an X-CSRF-Token header on POST/PUT/PATCH/DELETE.
If you enable use_cookies() or use_session_memory() without wiring use_csrf_protection, nestrs emits a tracing WARN at router build time. Treat this as a release blocker for any browser-facing endpoint that mutates state.

Cookies and sessions

Always pair cookie or session middleware with use_csrf_protection for any endpoint that accepts browser-originated mutations.

Guards and authentication

nestrs does not bundle a JWT or Passport library. Instead, you implement CanActivate (HTTP guards) or AuthStrategy (credential-validation strategies) and compose them on controllers or individual routes.

CanActivate guard

BearerToken extractor

For routes that unconditionally require a bearer token, use the BearerToken extractor directly — it returns 401 when the header is absent or malformed:
Use OptionalBearerToken when the header is optional:

AuthStrategyGuard

AuthStrategyGuard<S> wraps any type that implements AuthStrategy and can be derived as Default. Wire it onto a controller or individual route with #[use_guards]:

Body limits and timeouts

Set a maximum request body size and a per-request timeout for any public endpoint:

Production error sanitization

By default nestrs forwards internal error details to the client. Call enable_production_errors_from_env() to suppress stack traces and internal messages whenever NESTRS_ENV, APP_ENV, or RUST_ENV equals production or prod:
Call enable_production_errors() unconditionally if you want sanitization regardless of environment.

Pre-production checklist

Run through this list before deploying a browser-facing or multi-tenant API:
  • use_security_headers(SecurityHeaders::default()) is called, or helmet_like() for richer isolation.
  • CSP is set explicitly for HTML-serving endpoints.
  • enable_cors(...) uses an explicit origin allowlist — not CorsOptions::permissive().
  • allow_credentials(true) is not combined with a wildcard origin.
  • Cookie or session flows have use_csrf_protection(...) wired.
  • The csrf Cargo feature is enabled alongside cookies.
  • No tracing WARN about missing CSRF at startup.
  • use_rate_limit(...) is configured (or enforced at the edge).
  • use_body_limit(...) is set per endpoint class.
  • use_request_timeout(...) is set for public routes.
  • enable_production_errors_from_env() (or enable_production_errors()) is active.
  • cargo audit is passing locally and in CI.
  • Secrets are loaded from env / secret manager, not committed to source.
  • Logs do not contain tokens, passwords, or API keys.
The defaults for every control are listed in docs/src/secure-defaults.md (in the repository), which also includes the full secure-by-default matrix.