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
Calluse_security_headers with a SecurityHeaders value to inject protective HTTP headers on every response. SecurityHeaders::default() sets the most broadly applicable headers:
X-Content-Type-Options: nosniffX-Frame-Options: DENYReferrer-Policy: strict-origin-when-cross-originX-XSS-Protection: 0Permissions-Policy: geolocation=(), microphone=(), camera=()
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 callenable_cors. Pass a CorsOptions value with an explicit origin allowlist for browser clients:
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.
Rate limiting
use_rate_limit accepts a RateLimitOptions value. The defaults allow 100 requests per 60-second window per client IP:
cache-redis feature and call .redis(url, key_prefix):
Route-level throttling
Where the global rate limiter applies one budget to everything,use_throttler applies per-route budgets that individual handlers declare with decorators:
#[throttle(n, "second" | "minute" | "hour")]overrides the global spec for that route; rejected requests get429withRetry-AfterandX-RateLimit-Remainingheaders.#[skip_throttle]exempts a route entirely.ThrottlerOptions.globalis the fallback for undecorated routes —Nonemeans only explicitly decorated routes are throttled.- Like the rate limiter, the throttler supports a shared Redis backend (
cache-redisfeature) and inherits the trusted-proxy hop count (below).
Proxy topology and client identity
Both the rate limiter and the throttler key on the client IP, and theClientIp extractor exposes it to handlers. Behind a reverse proxy or load balancer, the socket address is the proxy’s — so client identity has to come from X-Forwarded-For / X-Real-IP. Those headers are attacker-spoofable, so nestrs never trusts them unless you declare your topology:
use_trusted_proxy_headers(hops)declares how many trusted proxies sit in front. The client address is read right-most-first: with the commonclient → LB → apptopology, the entry appended by your load balancer is used and any attacker-supplied prefix is ignored.- Forwarded headers are never consulted without this setting — trusting them by default would allow trivial IP-based rate-limit bypass.
- The rate limiter and throttler inherit the hop count automatically, so they key on the same identity as
ClientIp. Divergent per-component overrides are logged as atracingWARN. - Common topologies: direct exposure → omit the call (default 0 hops); one load balancer →
1; LB + CDN →2(count only hops you control and trust).
CSRF protection
CSRF protection targets cookie-based browser flows. Bearer token APIs inAuthorization 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.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
- In-memory sessions
use_csrf_protection for any endpoint that accepts browser-originated mutations.
Guards and authentication
For token validation you implementCanActivate (HTTP guards) or AuthStrategy (credential-validation strategies) and compose them on controllers or individual routes. For full OAuth2 — client flows, JWKS-based resource-server validation, social providers — see the OAuth2 guide; for per-row authorization see the authorization guide.
CanActivate guard
BearerToken extractor
For routes that unconditionally require a bearer token, use theBearerToken extractor directly — it returns 401 when the header is absent or malformed:
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
5xx JSON bodies are sanitized by default whenever the runtime environment is production — the first non-empty value ofNESTRS_ENV, APP_ENV, or RUST_ENV is compared (case-insensitively) against production / prod. Sanitization replaces the internal message with "An unexpected error occurred", drops any errors payload, and inserts the canonical reason phrase, so stack traces and internal detail never reach clients. No builder call is needed in production; enable_production_errors_from_env() re-reads the environment (kept for explicitness), and enable_production_errors() forces sanitization on in any environment — useful for staging that runs with NESTRS_ENV=staging:
disable_production_errors() opts out even in production — for internal admin services behind a trusted boundary that want detailed errors.
Pre-production checklist
Run through this list before deploying a browser-facing or multi-tenant API:Headers and CORS
Headers and CORS
use_security_headers(SecurityHeaders::default())is called, orhelmet_like()for richer isolation.- CSP is set explicitly for HTML-serving endpoints.
enable_cors(...)uses an explicit origin allowlist — notCorsOptions::permissive().allow_credentials(true)is not combined with a wildcard origin.
Rate limiting and timeouts
Rate limiting and timeouts
use_rate_limit(...)is configured (or enforced at the edge).use_throttler(...)covers expensive routes with tighter#[throttle]budgets where needed.use_body_limit(...)is set per endpoint class.use_request_timeout(...)is set for public routes.
Proxy topology
Proxy topology
use_trusted_proxy_headers(hops)matches the real proxy chain — 0 if directly exposed.- No component overrides
trusted_proxy_hopsto a divergent value (WARN at startup if so).
Errors and dependencies
Errors and dependencies
- 5xx sanitization is active (default in production;
disable_production_errors()only behind a trusted boundary). cargo auditis 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.
docs/src/secure-defaults.md (in the repository), which also includes the full secure-by-default matrix.