feat: comprehensive security hardening for Nova#367
Open
Conversation
Set HttpOnly, Secure, SameSite=Lax, and Path=/ on all session cookies to mitigate XSS cookie theft, man-in-the-middle attacks, and CSRF. Replace rand:uniform/1 with crypto:strong_rand_bytes/1 for cryptographically secure session ID generation. Cookie options are configurable via the session_cookie_opts application environment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a configurable plugin that sets security headers on every response: - X-Frame-Options: DENY (clickjacking protection) - X-Content-Type-Options: nosniff (MIME sniffing protection) - X-XSS-Protection: 1; mode=block - Referrer-Policy: strict-origin-when-cross-origin - Permissions-Policy: restrictive defaults Optional HSTS and CSP support via plugin options. All headers are overridable per-application. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sliding window rate limiter using ETS counters. Tracks requests per client IP within configurable time windows. Returns 429 with Retry-After header when limit exceeded. Supports path-prefix filtering and custom key functions for flexible rate limiting (e.g. per API key, per user). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add nova_session:rotate/1 for session fixation prevention — generates
new session ID and migrates data on privilege changes (login/logout)
- Add rotate_session/2 callback to nova_session behaviour (optional)
- Add session timestamps (created_at, last_accessed) to ETS backend
- Add periodic cleanup of expired sessions (configurable intervals)
- session_max_age (default 24h) and session_idle_timeout (default 1h)
configurable via application environment
- Backward-compatible with legacy {SessionId, Data} tuple format
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change default Access-Control-Allow-Headers from "*" to "Content-Type, Authorization" and Access-Control-Allow-Methods from "*" to "GET, POST, PUT, DELETE, OPTIONS". Both are now configurable via allow_headers and allow_methods plugin options. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Redirects HTTP requests to HTTPS with 301 status. Supports custom host/port override, query string preservation, and path exclusions for health checks. Use alongside nova_secure_headers_plugin's HSTS option for complete TLS enforcement. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OTP logger filter that redacts sensitive parameters from log output. Default filtered keys: password, secret, token, api_key, authorization, passwd, credit_card. Configurable via filter_parameters app env. Supports case-insensitive partial matching, nested maps, and both atom and binary keys. Can be used as a logger filter or called directly via redact_params/1,2. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The extra_msg variable in nova_error.dtl was rendered with |safe, bypassing erlydtl's auto-escaping. While the content is from internal crash info, this is a defense-in-depth fix. Changed the error controller to use newlines instead of <br /> HTML tags. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reject path segments containing ".." or "." in wildcard pathinfo before joining with the static directory path. Without this check, a request like /static/../../../etc/passwd could escape the configured static directory. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Covers sessions, CSRF, HTTP headers, TLS, rate limiting, CORS, XSS, SQL injection, authorization, logging, and BEAM-specific concerns. Includes recommended plugin stack for production deployments and links to ERLEF, Phoenix, and OWASP references. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Comprehensive security hardening based on ERLEF Web App Security Best Practices and Phoenix security recommendations.
Commits
HttpOnly,Secure,SameSite=Lax,Path=/on all session cookies; replacerand:uniformwithcrypto:strong_rand_bytesfor session IDs; configurable viasession_cookie_optsapp envnova_secure_headers_plugin) — SetsX-Frame-Options,X-Content-Type-Options,X-XSS-Protection,Referrer-Policy,Permissions-Policyby default; optional HSTS and CSP supportnova_rate_limit_plugin) — Sliding window ETS-based rate limiter per client IP; configurable paths, limits, windows, and custom key functions; returns 429 withRetry-Afternova_session:rotate/1) for fixation prevention; session timestamps with configurable max age (24h) and idle timeout (1h); periodic cleanup of expired ETS entries*for headers/methods to explicitContent-Type, AuthorizationandGET, POST, PUT, DELETE, OPTIONS; both now configurablenova_force_ssl_plugin) — HTTP→HTTPS redirect with 301; supports custom host/port, query string preservation, and path exclusionsnova_log_filter) — OTP logger filter for redacting sensitive params (password, secret, token, etc.); configurable filter list|safefilter fromnova_error.dtlso erlydtl auto-escaping is not bypassed..and.segments innova_file_controllerwildcard pathinfoerl_crash.dumpSecurity audit findings addressed
rand:uniformcrypto:strong_rand_bytesrotate/1on privilege change|safebypassing..and.rejectedTest plan
Set-Cookieheaders in browser dev tools🤖 Generated with Claude Code