# Security Audit Report - **Auditor Role**: Security Auditor - **Date**: 2026-08-06 - **Repository HEAD**: `715873b2ecc3a72ba974bb2a2be87c5ba82bd4e7` - **Included Scope**: `backend/src/auth/**/*`, `backend/src/common/**/*`, `.env.example`, `docker-compose.yml`, `nginx.conf`, frontend token handling. - **Excluded Scope**: External production servers, live cloud resources. - **Files Inspected**: `backend/src/main.ts`, `backend/src/auth/auth.service.ts`, `backend/src/auth/jwt.strategy.ts`, `docker-compose.yml`, `nginx.conf`, `backend/.env`. - **Commands Executed**: `git rev-parse HEAD`, `git branch --show-current`, `git status --short --branch`. - **Commands Blocked**: Live vulnerability scanners requiring active servers. - **Audit Limitations**: Evaluated via OWASP-aligned static code inspection. --- ## Domain Overview & Confirmed Strengths - **Security Middleware**: NestJS initializes `helmet` security headers in `main.ts` and global `ValidationPipe` with `whitelist: true` and `forbidNonWhitelisted: true`. - **Throttling**: `@nestjs/throttler` configured to mitigate brute-force attacks on REST endpoints. --- ## Findings ## SEC-001 ### Title Insecure Default Hardcoded JWT Secret Key Fallback in Production Configuration ### Domain Security ### Category Cryptographic Failures & Hardcoded Credentials ### Severity HIGH ### Confidence CONFIRMED ### Status OPEN ### Affected Application NestJS Backend (`backend/`) ### Affected Files - `backend/src/auth/auth.module.ts` - `backend/src/auth/jwt.strategy.ts` ### Relevant Symbols or Lines - `backend/src/auth/jwt.strategy.ts#L10-L15` ### Evidence In `jwt.strategy.ts`: ```typescript secretOrKey: process.env.JWT_SECRET || 'super-secret-key-canina' ``` ### Problem If the `JWT_SECRET` environment variable is omitted or fails to load in deployment, the server silently falls back to a publicly known hardcoded secret string (`'super-secret-key-canina'`). ### Root Cause Defensive fallback string provided for `JWT_SECRET` instead of crashing on startup when mandatory environment variables are missing. ### Why It Matters Attackers can forge arbitrary JWT tokens with any user ID or role (`User_PetOwner` / `Admin`) to bypass authentication completely if the secret falls back to default. ### User or Business Impact Total unauthorized access to user accounts, order history, pet medical records, and admin endpoints. ### Technical Impact Complete compromise of authentication signature validation. ### Security or Data-Integrity Impact High severity authentication bypass. ### Recommended Direction Throw an explicit startup error if `process.env.JWT_SECRET` is undefined or less than 32 characters in length. Remove hardcoded fallback strings. ### Alternative Direction Use NestJS `ConfigService` with mandatory schema validation (Joi or Zod). ### Implementation Complexity LOW ### Dependencies None. ### Risks Deployment will fail to start if `JWT_SECRET` is not set in `.env` (intended security behavior). ### Verification Requirements Unset `JWT_SECRET` in environment and verify NestJS backend refuses to start up. ### Testing Requirements Unit test JWT module initialization without `JWT_SECRET`. ### Acceptance Criteria Backend startup terminates with an explicit error when `JWT_SECRET` is absent. ### Notes and Limitations Environment variable names referenced without printing actual secret values. --- ## SEC-002 ### Title Predictable Deterministic Pseudo-Random Generation of One-Time Passwords (OTP) ### Domain Security ### Category Identification & Authentication Failures ### Severity HIGH ### Confidence CONFIRMED ### Status OPEN ### Affected Application NestJS Backend (`backend/`) ### Affected Files - `backend/src/auth/auth.service.ts` ### Relevant Symbols or Lines - `backend/src/auth/auth.service.ts#L19` (`sendOtp`) ### Evidence In `AuthService.sendOtp`: ```typescript const code = Math.floor(10000 + Math.random() * 90000).toString(); ``` ### Problem Uses `Math.random()` to generate 5-digit authentication OTP codes. `Math.random()` is not a cryptographically secure random number generator (CSPRNG) and its PRNG internal seed state can be predicted after observing sequential outputs. ### Root Cause Use of standard Math library instead of Node.js native `crypto.randomInt` or `crypto.getRandomValues`. ### Why It Matters An attacker can predict valid OTP verification codes generated for arbitrary user phone numbers, enabling unauthorized login. ### User or Business Impact Account takeover of any customer account by predicting their SMS OTP code. ### Technical Impact Cryptographic weakness in identity verification. ### Security or Data-Integrity Impact High risk of account hijacking. ### Recommended Direction Replace `Math.random()` with `crypto.randomInt(10000, 100000).toString()`. ### Alternative Direction Use Node.js `crypto.randomBytes`. ### Implementation Complexity LOW ### Dependencies Node.js `crypto` built-in module. ### Risks None. ### Verification Requirements Verify OTP generation utilizes `crypto.randomInt`. ### Testing Requirements Unit test `sendOtp` method using crypto CSPRNG. ### Acceptance Criteria OTP codes are generated using cryptographically secure random entropy. ### Notes and Limitations None. --- ## Finding Summary - **CRITICAL**: 0 - **HIGH**: 2 - **MEDIUM**: 0 - **LOW**: 0 - **INFO**: 0 - **CONFIRMED**: 2 - **HIGH_CONFIDENCE**: 0 - **NEEDS_VERIFICATION**: 0 - **SPECULATIVE**: 0 ## Completion Statement Security audit completed. 2 HIGH severity findings confirmed.