Problem
Several environment variables silently fall back to insecure defaults when unset, which is a real security risk in any non-local environment:
src/middleware/authMiddleware.ts:14 — const SECRET_KEY = process.env.JWT_SECRET || 'defaultSecret';
→ If JWT_SECRET is missing in production, every token is signed and verified with the literal string 'defaultSecret'. Anyone who knows the source code can forge tokens.
src/config/data-source.ts:10 — password: process.env.DB_PASSWORD || "password"
→ Falls back to the literal "password".
src/config/data-source.ts:7-11 — host/port/user/db all default silently.
src/utils/email.utils.ts — uses EMAIL_USER / EMAIL_PASS / FRONTEND_URL with no validation; missing values produce confusing runtime errors instead of a clear startup failure.
src/modules/shared/middleware/rate-limit/domain/rate-limit-config.ts — many Number(process.env.X) || N patterns; if X is a non-numeric string, the fallback is silently used.
There is no centralized place where required env vars are validated when the process boots, so misconfiguration is discovered late (often only when a request hits a code path that needs the var).
Proposed Solution
- Add a runtime env-var schema using
zod (already a common choice and small) or envalid. Place it at src/config/env.ts.
- Define a schema that:
- Marks
JWT_SECRET, DATABASE_URL (or DB_*), REDIS_URL, EMAIL_USER, EMAIL_PASS, FRONTEND_URL as required in production.
- Allows safe local defaults only when
NODE_ENV !== 'production' and explicitly logs a warning.
- Coerces numeric vars (
PORT, all RATE_LIMIT_*) to number and rejects non-numeric input.
- Validates
NODE_ENV against the enum ['development', 'test', 'staging', 'production'].
- Export a typed, frozen
env object and replace all direct process.env.X reads in src/ with imports from src/config/env.ts.
- Call the validator in
src/index.ts before Express is constructed; on validation failure, log the missing/invalid keys and process.exit(1).
- Remove insecure literal fallbacks (
'defaultSecret', "password", etc.).
- Update
.env.example (create if missing) with the full required-vars list and short comments.
- Add a unit test that imports the schema, feeds it bad input, and asserts the validator throws.
Acceptance Criteria
Out of Scope
- Secret-management / vault integration.
- Rotating existing JWT secrets in deployed environments (ops concern).
Suggested Labels
security, enhancement, developer-experience
Problem
Several environment variables silently fall back to insecure defaults when unset, which is a real security risk in any non-local environment:
src/middleware/authMiddleware.ts:14—const SECRET_KEY = process.env.JWT_SECRET || 'defaultSecret';→ If
JWT_SECRETis missing in production, every token is signed and verified with the literal string'defaultSecret'. Anyone who knows the source code can forge tokens.src/config/data-source.ts:10—password: process.env.DB_PASSWORD || "password"→ Falls back to the literal
"password".src/config/data-source.ts:7-11— host/port/user/db all default silently.src/utils/email.utils.ts— usesEMAIL_USER/EMAIL_PASS/FRONTEND_URLwith no validation; missing values produce confusing runtime errors instead of a clear startup failure.src/modules/shared/middleware/rate-limit/domain/rate-limit-config.ts— manyNumber(process.env.X) || Npatterns; ifXis a non-numeric string, the fallback is silently used.There is no centralized place where required env vars are validated when the process boots, so misconfiguration is discovered late (often only when a request hits a code path that needs the var).
Proposed Solution
zod(already a common choice and small) orenvalid. Place it atsrc/config/env.ts.JWT_SECRET,DATABASE_URL(orDB_*),REDIS_URL,EMAIL_USER,EMAIL_PASS,FRONTEND_URLas required in production.NODE_ENV !== 'production'and explicitly logs a warning.PORT, allRATE_LIMIT_*) tonumberand rejects non-numeric input.NODE_ENVagainst the enum['development', 'test', 'staging', 'production'].envobject and replace all directprocess.env.Xreads insrc/with imports fromsrc/config/env.ts.src/index.tsbefore Express is constructed; on validation failure, log the missing/invalid keys andprocess.exit(1).'defaultSecret',"password", etc.)..env.example(create if missing) with the full required-vars list and short comments.Acceptance Criteria
src/config/env.tsexists, validates all required vars, and exports a typedenvobject.process.env.Xreads remain insidesrc/(except insideenv.tsitself); grep returns clean.JWT_SECRET || 'defaultSecret'andDB_PASSWORD || "password"are removed..env.exampleenumerates every required and optional variable.Out of Scope
Suggested Labels
security,enhancement,developer-experience