Security Hardening
LaunchKit Pro includes a configurable security foundation — rate limiting, optional CAPTCHA, security headers, CORS strict mode, and expanded audit logging.
Defaults (safe install)
| Feature | Default | Notes |
|---|---|---|
| Rate limiting | RATE_LIMIT_ENABLED=true | In-memory IP/user buckets |
| CAPTCHA | CAPTCHA_ENABLED=false | Forms work without external provider |
| CAPTCHA provider | MOCK | No keys required |
| Security headers | SECURITY_HEADERS_ENABLED=true | Helmet on API, conservative headers on Next.js |
| CORS strict mode | CORS_STRICT_MODE=true | Only allowed origins (+ FRONTEND_URL) |
| Audit logging | AUDIT_LOG_ENABLED=true | Secrets never stored in metadata |
No paid CAPTCHA or external security service is required for a normal install.
Rate limiting
See Rate Limiting for tier details and env vars.
Friendly 429 response:
{
"statusCode": 429,
"message": ["Too many requests. Please try again later."]
}CAPTCHA
Providers: MOCK, TURNSTILE, RECAPTCHA.
CAPTCHA_ENABLED=false— verification skipped; forms unchanged.CAPTCHA_PROVIDER=MOCK— accepts test tokens (mock-valid,mock_*); no external API.- Turnstile/reCAPTCHA — foundation only; set secret keys on backend when ready.
Applied only when configured:
- Contact form (
CAPTCHA_REQUIRED_FOR_CONTACT) - Support tickets (
CAPTCHA_REQUIRED_FOR_SUPPORT) - Registration (
CAPTCHA_REQUIRED_FOR_SIGNUP)
Public status: GET /security/status
Admin status: GET /admin/security/status
Frontend admin page: /admin/security
CAPTCHA secret keys stay backend-only.
Security headers
Backend (NestJS): Helmet when SECURITY_HEADERS_ENABLED=true; X-Powered-By disabled; JSON body limit 1mb.
Frontend (Next.js): X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy.
A strict Content-Security-Policy is not enabled by default — it can break API calls, uploads, and docs embeds. Add CSP in production when you have tested your asset origins.
CORS
Allowed origins: FRONTEND_URL, CORS_ALLOWED_ORIGINS, and http://localhost:3000.
With CORS_STRICT_MODE=true, development localhost bypass on arbitrary ports is disabled — add extra origins to CORS_ALLOWED_ORIGINS (e.g. http://localhost:5173 for local docs).
Rejected origins return: Origin not allowed by CORS.
Audit logs
See Audit Logs. Metadata is sanitized — passwords, tokens, API keys, license keys, and webhook secrets are never logged.
Production recommendations
- Keep
RATE_LIMIT_ENABLED=truebehind Nginx withTRUST_PROXY=true. - Enable CAPTCHA on public contact when exposed to the internet.
- Set
CORS_STRICT_MODE=trueand list only your app/docs origins. - Set
API_DOCS_ENABLED=falsein production if Swagger is not needed. - Use strong JWT secrets and rotate provider keys via env — never commit
.env.