fix(security): add production env validation and sanitize .env.example

- Add startup env validation that fails fast in production if critical vars
  (JWT_SECRET, JWT_REFRESH_SECRET, DATABASE_URL, CORS_ORIGINS, REDIS_HOST)
  are missing
- Fix CORS_ORIGINS to throw in production instead of defaulting to localhost
- Replace hardcoded dev passwords in .env.example with CHANGE_ME placeholders
- Add missing vars to .env.example (CORS_ORIGINS, SMTP_*, FIREBASE, LOG_LEVEL)
- Warn on missing optional payment/storage vars at startup

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-08 06:12:39 +07:00
parent d77c14e549
commit e89c8f5810
4 changed files with 112 additions and 10 deletions

View File

@@ -1,12 +1,13 @@
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { LoggerService } from '@modules/shared';
import { LoggerService, validateEnv } from '@modules/shared';
import cookieParser from 'cookie-parser';
import helmet from 'helmet';
import { AppModule } from './app.module';
async function bootstrap() {
validateEnv();
const app = await NestFactory.create(AppModule, {
bufferLogs: true,
rawBody: true,
@@ -67,7 +68,11 @@ async function bootstrap() {
app.use(cookieParser());
// ── CORS ──
const allowedOrigins = (process.env['CORS_ORIGINS'] ?? 'http://localhost:3000')
const corsOrigins = process.env['CORS_ORIGINS'];
if (!corsOrigins && process.env['NODE_ENV'] === 'production') {
throw new Error('CORS_ORIGINS must be set in production');
}
const allowedOrigins = (corsOrigins ?? 'http://localhost:3000')
.split(',')
.map((o) => o.trim());
app.enableCors({