π΄ Where to work
Primary file: api/src/auth/auth.module.ts β line 12, replace "dev-secret-change-me" fallback with fatal error
Secondary file: api/src/gateways/gateways.module.ts β line 15-17, replace "dev-insecure-secret-change-me" fallback
New file: api/src/config/jwt.config.ts β create shared JWT config factory
Reference: api/src/config/env.ts β already validates JWT_SECRET, use this pattern
Problem Statement
Two JwtModule registrations use hardcoded fallback secrets. In api/src/auth/auth.module.ts:12: secret: process.env.JWT_SECRET ?? "dev-secret-change-me". In api/src/gateways/gateways.module.ts:15-17: secret: secret ?? "dev-insecure-secret-change-me". If deployed without JWT_SECRET set, anyone can forge JWTs using these known strings.
Evidence
// api/src/auth/auth.module.ts:12 β silently falls back to hardcoded secret
secret: process.env.JWT_SECRET ?? "dev-secret-change-me",
// api/src/gateways/gateways.module.ts:15-17 β warns but still falls back in non-prod
const secret = process.env.JWT_SECRET
if (!secret && process.env.NODE_ENV === "production") {
throw new Error("JWT_SECRET must be set in production for WebSocket auth")
}
return { secret: secret ?? "dev-insecure-secret-change-me", ... }
Impact
If JWT_SECRET is unset in production, attackers can forge JWTs using "dev-secret-change-me" and authenticate as any user. Critical credential disclosure.
Proposed Solution
Remove all fallback secrets. Create shared JWT config factory that throws on missing secret in all environments. Generate random secret in dev only (with clear warning).
Acceptance Criteria
File Map
api/src/config/jwt.config.ts [NEW] β shared JWT config factory, reads from validated Env, throws on missing secret
api/src/auth/auth.module.ts [EDIT] β use shared config, remove ?? "dev-secret-change-me"
api/src/gateways/gateways.module.ts [EDIT] β use shared config, remove ?? "dev-insecure-secret-change-me"
api/src/config/env.ts [VERIFY] β JWT_SECRET already required via z.string().min(1), ensure strict
Testing Strategy
- Unit: Test that factory throws when JWT_SECRET is empty
- Unit: Test that factory returns correct config when JWT_SECRET is set
- Integration: Verify app starts with JWT_SECRET set, crashes without it
Security Considerations
This eliminates a hardcoded credential. Random dev secret must be clearly marked as unsafe for production. No fallback in any environment.
π΄ Where to work
Primary file:
api/src/auth/auth.module.tsβ line 12, replace"dev-secret-change-me"fallback with fatal errorSecondary file:
api/src/gateways/gateways.module.tsβ line 15-17, replace"dev-insecure-secret-change-me"fallbackNew file:
api/src/config/jwt.config.tsβ create shared JWT config factoryReference:
api/src/config/env.tsβ already validates JWT_SECRET, use this patternProblem Statement
Two JwtModule registrations use hardcoded fallback secrets. In
api/src/auth/auth.module.ts:12:secret: process.env.JWT_SECRET ?? "dev-secret-change-me". Inapi/src/gateways/gateways.module.ts:15-17:secret: secret ?? "dev-insecure-secret-change-me". If deployed without JWT_SECRET set, anyone can forge JWTs using these known strings.Evidence
Impact
If JWT_SECRET is unset in production, attackers can forge JWTs using
"dev-secret-change-me"and authenticate as any user. Critical credential disclosure.Proposed Solution
Remove all fallback secrets. Create shared JWT config factory that throws on missing secret in all environments. Generate random secret in dev only (with clear warning).
Acceptance Criteria
File Map
api/src/config/jwt.config.ts[NEW] β shared JWT config factory, reads from validated Env, throws on missing secretapi/src/auth/auth.module.ts[EDIT] β use shared config, remove?? "dev-secret-change-me"api/src/gateways/gateways.module.ts[EDIT] β use shared config, remove?? "dev-insecure-secret-change-me"api/src/config/env.ts[VERIFY] β JWT_SECRET already required viaz.string().min(1), ensure strictTesting Strategy
Security Considerations
This eliminates a hardcoded credential. Random dev secret must be clearly marked as unsafe for production. No fallback in any environment.