diff --git a/backend/docker-compose.yml b/backend/docker-compose.yml index eaa9e52..8392469 100644 --- a/backend/docker-compose.yml +++ b/backend/docker-compose.yml @@ -1,11 +1,11 @@ -version: '3.8' services: db: image: postgres:14.1-alpine restart: unless-stopped environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres + - POSTGRES_USER=${DATABASE_USER:-postgres} + # SECURITY FIX: Enforce DATABASE_PASSWORD at container startup to prevent fallback to insecure or default credentials. + - POSTGRES_PASSWORD=${DATABASE_PASSWORD:?DATABASE_PASSWORD must be set} ports: - '5433:5432' networks: @@ -19,4 +19,4 @@ networks: volumes: db: - driver: local + driver: local \ No newline at end of file diff --git a/backend/mikro-orm.config.js b/backend/mikro-orm.config.js index 0f615a6..7efd2ee 100644 --- a/backend/mikro-orm.config.js +++ b/backend/mikro-orm.config.js @@ -1,12 +1,27 @@ +require('dotenv').config(); + +// SECURITY FIX: Replaced hardcoded ORM credentials with strict environment variable evaluation. +// This ensures the backend fails closed immediately if critical secrets are missing. +const requiredEnv = (name) => { + const value = process.env[name]; + + if (!value) { + throw new Error(`Missing required environment variable: ${name}`); + } + + return value; +}; + module.exports = { entities: ['./dist/domain/**/model/*.js'], - dbName: 'br-hackathon', + dbName: process.env.DATABASE_NAME || 'br-hackathon', migrations: { path: './src/persistance/migrations', }, type: 'postgresql', - - port: 5433, - user: 'postgres', - password: 'postgres', -}; + host: requiredEnv('DATABASE_HOST'), + port: Number(process.env.DATABASE_PORT || 5433), + user: requiredEnv('DATABASE_USER'), + // SECURITY FIX: Database password is now securely injected via environment variables. + password: requiredEnv('DATABASE_PASSWORD'), +}; \ No newline at end of file diff --git a/backend/src/main.ts b/backend/src/main.ts index 59f093d..151365f 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -5,9 +5,21 @@ import { ApiModule } from './api/api.module'; function configureCors(app: INestApplication): void { if (process.env.NODE_ENV === 'development') { app.enableCors({ origin: '*' }); - } else { - app.enableCors({ origin: process.env.ALLOWED_ORIGINS?.split(';') }); + return; } + + const allowedOrigins = process.env.ALLOWED_ORIGINS + ?.split(';') + .map((origin) => origin.trim()) + .filter(Boolean); + + // SECURITY FIX: Enforce a strict CORS policy in production. + // The application now fails closed if ALLOWED_ORIGINS is missing, preventing permissive wildcard access. + if (!allowedOrigins?.length) { + throw new Error('ALLOWED_ORIGINS must be configured outside development'); + } + + app.enableCors({ origin: allowedOrigins }); } async function bootstrap() { @@ -17,6 +29,7 @@ async function bootstrap() { app.useGlobalPipes(new ValidationPipe({ transform: true })); - await app.listen(3001); + await app.listen(Number(process.env.PORT ?? 3001)); } -bootstrap(); + +bootstrap(); \ No newline at end of file