canina/docs/audit/10-security-audit.md
2026-08-06 20:54:44 +03:30

5.4 KiB

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:

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.

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:

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.

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.